Package taskcoachlib :: Package thirdparty :: Package aui :: Module framemanager
[hide private]
[frames] | no frames]

Source Code for Module taskcoachlib.thirdparty.aui.framemanager

    1  # --------------------------------------------------------------------------- # 
    2  # AUI Library wxPython IMPLEMENTATION 
    3  # 
    4  # Original C++ Code From Kirix (wxAUI). You Can Find It At: 
    5  # 
    6  #    License: wxWidgets license 
    7  # 
    8  # http:#www.kirix.com/en/community/opensource/wxaui/about_wxaui.html 
    9  # 
   10  # Current wxAUI Version Tracked: wxWidgets 2.9.4 SVN HEAD 
   11  # 
   12  # 
   13  # Python Code By: 
   14  # 
   15  # Andrea Gavana, @ 23 Dec 2005 
   16  # Latest Revision: 25 Apr 2012, 21.00 GMT 
   17  # 
   18  # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please 
   19  # Write To Me At: 
   20  # 
   21  # andrea.gavana@gmail.com 
   22  # andrea.gavana@maerskoil.com 
   23  # 
   24  # Or, Obviously, To The wxPython Mailing List!!! 
   25  # 
   26  # End Of Comments 
   27  # --------------------------------------------------------------------------- # 
   28   
   29  """ 
   30  Description 
   31  =========== 
   32   
   33  `framemanager.py` is the central module of the AUI class framework. 
   34   
   35  :class:`AuiManager` manages the panes associated with it for a particular :class:`Frame`, using 
   36  a pane's :class:`AuiPaneInfo` information to determine each pane's docking and floating 
   37  behavior. AuiManager uses wxPython' sizer mechanism to plan the layout of each frame. 
   38  It uses a replaceable dock art class to do all drawing, so all drawing is localized 
   39  in one area, and may be customized depending on an application's specific needs. 
   40   
   41  AuiManager works as follows: the programmer adds panes to the class, or makes 
   42  changes to existing pane properties (dock position, floating state, show state, etc...). 
   43  To apply these changes, AuiManager's :meth:`AuiManager.Update() <AuiManager.Update>` function is called. This batch 
   44  processing can be used to avoid flicker, by modifying more than one pane at a time, 
   45  and then "committing" all of the changes at once by calling `Update()`. 
   46   
   47  Panes can be added quite easily:: 
   48   
   49      text1 = wx.TextCtrl(self, -1) 
   50      text2 = wx.TextCtrl(self, -1) 
   51      self._mgr.AddPane(text1, AuiPaneInfo().Left().Caption("Pane Number One")) 
   52      self._mgr.AddPane(text2, AuiPaneInfo().Bottom().Caption("Pane Number Two")) 
   53   
   54      self._mgr.Update() 
   55   
   56   
   57  Later on, the positions can be modified easily. The following will float an 
   58  existing pane in a tool window:: 
   59   
   60      self._mgr.GetPane(text1).Float() 
   61   
   62   
   63  Layers, Rows and Directions, Positions 
   64  ====================================== 
   65   
   66  Inside AUI, the docking layout is figured out by checking several pane parameters. 
   67  Four of these are important for determining where a pane will end up. 
   68   
   69  **Direction** - Each docked pane has a direction, `Top`, `Bottom`, `Left`, `Right`, or `Center`. 
   70  This is fairly self-explanatory. The pane will be placed in the location specified 
   71  by this variable. 
   72   
   73  **Position** - More than one pane can be placed inside of a "dock". Imagine two panes 
   74  being docked on the left side of a window. One pane can be placed over another. 
   75  In proportionally managed docks, the pane position indicates it's sequential position, 
   76  starting with zero. So, in our scenario with two panes docked on the left side, the 
   77  top pane in the dock would have position 0, and the second one would occupy position 1. 
   78   
   79  **Row** - A row can allow for two docks to be placed next to each other. One of the most 
   80  common places for this to happen is in the toolbar. Multiple toolbar rows are allowed, 
   81  the first row being in row 0, and the second in row 1. Rows can also be used on 
   82  vertically docked panes. 
   83   
   84  **Layer** - A layer is akin to an onion. Layer 0 is the very center of the managed pane. 
   85  Thus, if a pane is in layer 0, it will be closest to the center window (also sometimes 
   86  known as the "content window"). Increasing layers "swallow up" all layers of a lower 
   87  value. This can look very similar to multiple rows, but is different because all panes 
   88  in a lower level yield to panes in higher levels. The best way to understand layers 
   89  is by running the AUI sample (`AUI.py`). 
   90  """ 
   91   
   92  __author__ = "Andrea Gavana <andrea.gavana@gmail.com>" 
   93  __date__ = "31 March 2009" 
   94   
   95   
   96  import wx 
   97  import time 
   98  import types 
   99  import warnings 
  100   
  101  import auibar 
  102  import auibook 
  103  import tabmdi 
  104  import dockart 
  105  import tabart 
  106   
  107  from aui_utilities import Clip, PaneCreateStippleBitmap, GetDockingImage, GetSlidingPoints 
  108   
  109  from aui_constants import * 
  110   
  111  # Define this as a translation function 
  112  _ = wx.GetTranslation 
  113   
  114  _winxptheme = False 
  115  if wx.Platform == "__WXMSW__": 
  116      try: 
  117          import winxptheme 
  118          _winxptheme = True 
  119      except ImportError: 
  120          pass 
  121   
  122  # wxPython version string 
  123  _VERSION_STRING = wx.VERSION_STRING 
  124   
  125  # AUI Events 
  126  wxEVT_AUI_PANE_BUTTON = wx.NewEventType() 
  127  wxEVT_AUI_PANE_CLOSE = wx.NewEventType() 
  128  wxEVT_AUI_PANE_MAXIMIZE = wx.NewEventType() 
  129  wxEVT_AUI_PANE_RESTORE = wx.NewEventType() 
  130  wxEVT_AUI_RENDER = wx.NewEventType() 
  131  wxEVT_AUI_FIND_MANAGER = wx.NewEventType() 
  132  wxEVT_AUI_PANE_MINIMIZE = wx.NewEventType() 
  133  wxEVT_AUI_PANE_MIN_RESTORE = wx.NewEventType() 
  134  wxEVT_AUI_PANE_FLOATING = wx.NewEventType() 
  135  wxEVT_AUI_PANE_FLOATED = wx.NewEventType() 
  136  wxEVT_AUI_PANE_DOCKING = wx.NewEventType() 
  137  wxEVT_AUI_PANE_DOCKED = wx.NewEventType() 
  138  wxEVT_AUI_PANE_ACTIVATED = wx.NewEventType() 
  139  wxEVT_AUI_PERSPECTIVE_CHANGED = wx.NewEventType() 
  140   
  141  EVT_AUI_PANE_BUTTON = wx.PyEventBinder(wxEVT_AUI_PANE_BUTTON, 0) 
  142  """ Fires an event when the user left-clicks on a pane button. """ 
  143  EVT_AUI_PANE_CLOSE = wx.PyEventBinder(wxEVT_AUI_PANE_CLOSE, 0) 
  144  """ A pane in `AuiManager` has been closed. """ 
  145  EVT_AUI_PANE_MAXIMIZE = wx.PyEventBinder(wxEVT_AUI_PANE_MAXIMIZE, 0) 
  146  """ A pane in `AuiManager` has been maximized. """ 
  147  EVT_AUI_PANE_RESTORE = wx.PyEventBinder(wxEVT_AUI_PANE_RESTORE, 0) 
  148  """ A pane in `AuiManager` has been restored from a maximized state. """ 
  149  EVT_AUI_RENDER = wx.PyEventBinder(wxEVT_AUI_RENDER, 0) 
  150  """ Fires an event every time the AUI frame is being repainted. """ 
  151  EVT_AUI_FIND_MANAGER = wx.PyEventBinder(wxEVT_AUI_FIND_MANAGER, 0) 
  152  """ Used to find which AUI manager is controlling a certain pane. """ 
  153  EVT_AUI_PANE_MINIMIZE = wx.PyEventBinder(wxEVT_AUI_PANE_MINIMIZE, 0) 
  154  """ A pane in `AuiManager` has been minimized. """ 
  155  EVT_AUI_PANE_MIN_RESTORE = wx.PyEventBinder(wxEVT_AUI_PANE_MIN_RESTORE, 0) 
  156  """ A pane in `AuiManager` has been restored from a minimized state. """ 
  157  EVT_AUI_PANE_FLOATING = wx.PyEventBinder(wxEVT_AUI_PANE_FLOATING, 0) 
  158  """ A pane in `AuiManager` is about to be floated. """ 
  159  EVT_AUI_PANE_FLOATED = wx.PyEventBinder(wxEVT_AUI_PANE_FLOATED, 0) 
  160  """ A pane in `AuiManager` has been floated. """ 
  161  EVT_AUI_PANE_DOCKING = wx.PyEventBinder(wxEVT_AUI_PANE_DOCKING, 0) 
  162  """ A pane in `AuiManager` is about to be docked. """ 
  163  EVT_AUI_PANE_DOCKED = wx.PyEventBinder(wxEVT_AUI_PANE_DOCKED, 0) 
  164  """ A pane in `AuiManager` has been docked. """ 
  165  EVT_AUI_PANE_ACTIVATED = wx.PyEventBinder(wxEVT_AUI_PANE_ACTIVATED, 0) 
  166  """ A pane in `AuiManager` has been activated. """ 
  167  EVT_AUI_PERSPECTIVE_CHANGED = wx.PyEventBinder(wxEVT_AUI_PERSPECTIVE_CHANGED, 0) 
  168  """ The layout in `AuiManager` has been changed. """ 
  169   
  170  # ---------------------------------------------------------------------------- # 
  171   
172 -class AuiDockInfo(object):
173 """ A class to store all properties of a dock. """ 174
175 - def __init__(self):
176 """ 177 Default class constructor. 178 Used internally, do not call it in your code! 179 """ 180 181 object.__init__(self) 182 183 self.dock_direction = 0 184 self.dock_layer = 0 185 self.dock_row = 0 186 self.size = 0 187 self.min_size = 0 188 self.resizable = True 189 self.fixed = False 190 self.toolbar = False 191 self.rect = wx.Rect() 192 self.panes = []
193 194
195 - def IsOk(self):
196 """ 197 Returns whether a dock is valid or not. 198 199 In order to be valid, a dock needs to have a non-zero `dock_direction`. 200 """ 201 202 return self.dock_direction != 0
203 204
205 - def IsHorizontal(self):
206 """ Returns whether the dock is horizontal or not. """ 207 208 return self.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]
209 210
211 - def IsVertical(self):
212 """ Returns whether the dock is vertical or not. """ 213 214 return self.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER]
215 216 217 # ---------------------------------------------------------------------------- # 218
219 -class AuiDockingGuideInfo(object):
220 """ A class which holds information about VS2005 docking guide windows. """ 221
222 - def __init__(self, other=None):
223 """ 224 Default class constructor. 225 Used internally, do not call it in your code! 226 227 :param `other`: another instance of :class:`AuiDockingGuideInfo`. 228 """ 229 230 if other: 231 self.Assign(other) 232 else: 233 # window representing the docking target 234 self.host = None 235 # dock direction (top, bottom, left, right, center) 236 self.dock_direction = AUI_DOCK_NONE
237 238
239 - def Assign(self, other):
240 """ 241 Assigns the properties of the `other` :class:`AuiDockingGuideInfo` to `self`. 242 243 :param `other`: another instance of :class:`AuiDockingGuideInfo`. 244 """ 245 246 self.host = other.host 247 self.dock_direction = other.dock_direction
248 249
250 - def Host(self, h):
251 """ 252 Hosts a docking guide window. 253 254 :param `h`: an instance of :class:`AuiDockingGuideWindow` or :class:`AuiDockingHintWindow`. 255 """ 256 257 self.host = h 258 return self
259 260
261 - def Left(self):
262 """ Sets the guide window to left docking. """ 263 264 self.dock_direction = AUI_DOCK_LEFT 265 return self
266 267
268 - def Right(self):
269 """ Sets the guide window to right docking. """ 270 271 self.dock_direction = AUI_DOCK_RIGHT 272 return self
273 274
275 - def Top(self):
276 """ Sets the guide window to top docking. """ 277 278 self.dock_direction = AUI_DOCK_TOP 279 return self
280 281
282 - def Bottom(self):
283 """ Sets the guide window to bottom docking. """ 284 285 self.dock_direction = AUI_DOCK_BOTTOM 286 return self
287 288
289 - def Center(self):
290 """ Sets the guide window to center docking. """ 291 292 self.dock_direction = AUI_DOCK_CENTER 293 return self
294 295
296 - def Centre(self):
297 """ Sets the guide window to centre docking. """ 298 299 self.dock_direction = AUI_DOCK_CENTRE 300 return self
301 302 303 # ---------------------------------------------------------------------------- # 304
305 -class AuiDockUIPart(object):
306 """ A class which holds attributes for a UI part in the interface. """ 307 308 typeCaption = 0 309 typeGripper = 1 310 typeDock = 2 311 typeDockSizer = 3 312 typePane = 4 313 typePaneSizer = 5 314 typeBackground = 6 315 typePaneBorder = 7 316 typePaneButton = 8 317
318 - def __init__(self):
319 """ 320 Default class constructor. 321 Used internally, do not call it in your code! 322 """ 323 324 self.orientation = wx.VERTICAL 325 self.type = 0 326 self.rect = wx.Rect()
327 328 329 # ---------------------------------------------------------------------------- # 330
331 -class AuiPaneButton(object):
332 """ A simple class which describes the caption pane button attributes. """ 333
334 - def __init__(self, button_id):
335 """ 336 Default class constructor. 337 Used internally, do not call it in your code! 338 339 :param integer `button_id`: the pane button identifier. 340 """ 341 342 self.button_id = button_id
343 344 345 # ---------------------------------------------------------------------------- # 346 347 # event declarations/classes 348
349 -class AuiManagerEvent(wx.PyCommandEvent):
350 """ A specialized command event class for events sent by :class:`AuiManager`. """ 351
352 - def __init__(self, eventType, id=1):
353 """ 354 Default class constructor. 355 356 :param integer `eventType`: the event kind; 357 :param integer `id`: the event identification number. 358 """ 359 360 wx.PyCommandEvent.__init__(self, eventType, id) 361 362 self.manager = None 363 self.pane = None 364 self.button = 0 365 self.veto_flag = False 366 self.canveto_flag = True 367 self.dc = None
368 369
370 - def SetManager(self, mgr):
371 """ 372 Associates a :class:`AuiManager` to the current event. 373 374 :param `mgr`: an instance of :class:`AuiManager`. 375 """ 376 377 self.manager = mgr
378 379
380 - def SetDC(self, pdc):
381 """ 382 Associates a :class:`DC` device context to this event. 383 384 :param `pdc`: a :class:`DC` device context object. 385 """ 386 387 self.dc = pdc
388 389
390 - def SetPane(self, p):
391 """ 392 Associates a :class:`AuiPaneInfo` instance to this event. 393 394 :param `p`: a :class:`AuiPaneInfo` instance. 395 """ 396 397 self.pane = p
398 399
400 - def SetButton(self, b):
401 """ 402 Associates a :class:`AuiPaneButton` instance to this event. 403 404 :param `b`: a :class:`AuiPaneButton` instance. 405 """ 406 407 self.button = b
408 409
410 - def GetManager(self):
411 """ Returns the associated :class:`AuiManager` (if any). """ 412 413 return self.manager
414 415
416 - def GetDC(self):
417 """ Returns the associated :class:`DC` device context (if any). """ 418 419 return self.dc
420 421
422 - def GetPane(self):
423 """ Returns the associated :class:`AuiPaneInfo` structure (if any). """ 424 425 return self.pane
426 427
428 - def GetButton(self):
429 """ Returns the associated :class:`AuiPaneButton` instance (if any). """ 430 431 return self.button
432 433
434 - def Veto(self, veto=True):
435 """ 436 Prevents the change announced by this event from happening. 437 438 It is in general a good idea to notify the user about the reasons for 439 vetoing the change because otherwise the applications behaviour (which 440 just refuses to do what the user wants) might be quite surprising. 441 442 :param bool `veto`: ``True`` to veto the event, ``False`` otherwise. 443 """ 444 445 self.veto_flag = veto
446 447
448 - def GetVeto(self):
449 """ Returns whether the event has been vetoed or not. """ 450 451 return self.veto_flag
452 453
454 - def SetCanVeto(self, can_veto):
455 """ 456 Sets whether the event can be vetoed or not. 457 458 :param bool `can_veto`: ``True`` if the event can be vetoed, ``False`` otherwise. 459 """ 460 461 self.canveto_flag = can_veto
462 463
464 - def CanVeto(self):
465 """ Returns whether the event can be vetoed and has been vetoed. """ 466 467 return self.canveto_flag and self.veto_flag
468 469 470 # ---------------------------------------------------------------------------- # 471
472 -class AuiPaneInfo(object):
473 """ 474 AuiPaneInfo specifies all the parameters for a pane. These parameters specify where 475 the pane is on the screen, whether it is docked or floating, or hidden. In addition, 476 these parameters specify the pane's docked position, floating position, preferred 477 size, minimum size, caption text among many other parameters. 478 """ 479 480 optionFloating = 2**0 481 optionHidden = 2**1 482 optionLeftDockable = 2**2 483 optionRightDockable = 2**3 484 optionTopDockable = 2**4 485 optionBottomDockable = 2**5 486 optionFloatable = 2**6 487 optionMovable = 2**7 488 optionResizable = 2**8 489 optionPaneBorder = 2**9 490 optionCaption = 2**10 491 optionGripper = 2**11 492 optionDestroyOnClose = 2**12 493 optionToolbar = 2**13 494 optionActive = 2**14 495 optionGripperTop = 2**15 496 optionMaximized = 2**16 497 optionDockFixed = 2**17 498 optionNotebookDockable = 2**18 499 optionMinimized = 2**19 500 optionLeftSnapped = 2**20 501 optionRightSnapped = 2**21 502 optionTopSnapped = 2**22 503 optionBottomSnapped = 2**23 504 optionFlyOut = 2**24 505 optionCaptionLeft = 2**25 506 507 buttonClose = 2**26 508 buttonMaximize = 2**27 509 buttonMinimize = 2**28 510 buttonPin = 2**29 511 512 buttonCustom1 = 2**30 513 buttonCustom2 = 2**31 514 buttonCustom3 = 2**32 515 516 savedHiddenState = 2**33 # used internally 517 actionPane = 2**34 # used internally 518 wasMaximized = 2**35 # used internally 519 needsRestore = 2**36 # used internally 520 521
522 - def __init__(self):
523 """ Default class constructor. """ 524 525 self.window = None 526 self.frame = None 527 self.state = 0 528 self.dock_direction = AUI_DOCK_LEFT 529 self.dock_layer = 0 530 self.dock_row = 0 531 self.dock_pos = 0 532 self.minimize_mode = AUI_MINIMIZE_POS_SMART 533 self.floating_pos = wx.Point(-1, -1) 534 self.floating_size = wx.Size(-1, -1) 535 self.best_size = wx.Size(-1, -1) 536 self.min_size = wx.Size(-1, -1) 537 self.max_size = wx.Size(-1, -1) 538 self.dock_proportion = 0 539 self.caption = "" 540 self.buttons = [] 541 self.name = "" 542 self.icon = wx.NullIcon 543 self.rect = wx.Rect() 544 self.notebook_id = -1 545 self.transparent = 255 546 self.needsTransparency = False 547 self.previousDockPos = None 548 self.previousDockSize = 0 549 self.snapped = 0 550 self.minimize_target = None 551 552 self.DefaultPane()
553 554
555 - def dock_direction_get(self):
556 """ 557 Getter for the `dock_direction`. 558 559 :see: :meth:`~AuiPaneInfo.dock_direction_set` for a set of valid docking directions. 560 """ 561 562 if self.IsMaximized(): 563 return AUI_DOCK_CENTER 564 else: 565 return self._dock_direction
566 567
568 - def dock_direction_set(self, value):
569 """ 570 Setter for the `dock_direction`. 571 572 :param integer `value`: the docking direction. This can be one of the following bits: 573 574 ============================ ======= ============================================= 575 Dock Flag Value Description 576 ============================ ======= ============================================= 577 ``AUI_DOCK_NONE`` 0 No docking direction. 578 ``AUI_DOCK_TOP`` 1 Top docking direction. 579 ``AUI_DOCK_RIGHT`` 2 Right docking direction. 580 ``AUI_DOCK_BOTTOM`` 3 Bottom docking direction. 581 ``AUI_DOCK_LEFT`` 4 Left docking direction. 582 ``AUI_DOCK_CENTER`` 5 Center docking direction. 583 ``AUI_DOCK_CENTRE`` 5 Centre docking direction. 584 ``AUI_DOCK_NOTEBOOK_PAGE`` 6 Automatic AuiNotebooks docking style. 585 ============================ ======= ============================================= 586 587 """ 588 589 self._dock_direction = value
590 591 dock_direction = property(dock_direction_get, dock_direction_set) 592
593 - def IsOk(self):
594 """ 595 Returns ``True`` if the :class:`AuiPaneInfo` structure is valid. 596 597 :note: A pane structure is valid if it has an associated window. 598 """ 599 600 return self.window != None
601 602
603 - def IsMaximized(self):
604 """ Returns ``True`` if the pane is maximized. """ 605 606 return self.HasFlag(self.optionMaximized)
607 608
609 - def IsMinimized(self):
610 """ Returns ``True`` if the pane is minimized. """ 611 612 return self.HasFlag(self.optionMinimized)
613 614
615 - def IsFixed(self):
616 """ Returns ``True`` if the pane cannot be resized. """ 617 618 return not self.HasFlag(self.optionResizable)
619 620
621 - def IsResizeable(self):
622 """ Returns ``True`` if the pane can be resized. """ 623 624 return self.HasFlag(self.optionResizable)
625 626
627 - def IsShown(self):
628 """ Returns ``True`` if the pane is currently shown. """ 629 630 return not self.HasFlag(self.optionHidden)
631 632
633 - def IsFloating(self):
634 """ Returns ``True`` if the pane is floating. """ 635 636 return self.HasFlag(self.optionFloating)
637 638
639 - def IsDocked(self):
640 """ Returns ``True`` if the pane is docked. """ 641 642 return not self.HasFlag(self.optionFloating)
643 644
645 - def IsToolbar(self):
646 """ Returns ``True`` if the pane contains a toolbar. """ 647 648 return self.HasFlag(self.optionToolbar)
649 650
651 - def IsTopDockable(self):
652 """ 653 Returns ``True`` if the pane can be docked at the top 654 of the managed frame. 655 """ 656 657 return self.HasFlag(self.optionTopDockable)
658 659
660 - def IsBottomDockable(self):
661 """ 662 Returns ``True`` if the pane can be docked at the bottom 663 of the managed frame. 664 """ 665 666 return self.HasFlag(self.optionBottomDockable)
667 668
669 - def IsLeftDockable(self):
670 """ 671 Returns ``True`` if the pane can be docked at the left 672 of the managed frame. 673 """ 674 675 return self.HasFlag(self.optionLeftDockable)
676 677
678 - def IsRightDockable(self):
679 """ 680 Returns ``True`` if the pane can be docked at the right 681 of the managed frame. 682 """ 683 684 return self.HasFlag(self.optionRightDockable)
685 686
687 - def IsDockable(self):
688 """ Returns ``True`` if the pane can be docked. """ 689 690 return self.IsTopDockable() or self.IsBottomDockable() or self.IsLeftDockable() or \ 691 self.IsRightDockable() or self.IsNotebookDockable()
692 693
694 - def IsFloatable(self):
695 """ 696 Returns ``True`` if the pane can be undocked and displayed as a 697 floating window. 698 """ 699 700 return self.HasFlag(self.optionFloatable)
701 702
703 - def IsMovable(self):
704 """ 705 Returns ``True`` if the docked frame can be undocked or moved to 706 another dock position. 707 """ 708 709 return self.HasFlag(self.optionMovable)
710 711
712 - def IsDestroyOnClose(self):
713 """ 714 Returns ``True`` if the pane should be destroyed when it is closed. 715 716 Normally a pane is simply hidden when the close button is clicked. Calling :meth:`~AuiPaneInfo.DestroyOnClose` 717 with a ``True`` input parameter will cause the window to be destroyed when the user clicks 718 the pane's close button. 719 """ 720 721 return self.HasFlag(self.optionDestroyOnClose)
722 723
724 - def IsNotebookDockable(self):
725 """ 726 Returns ``True`` if a pane can be docked on top to another to create a 727 :class:`~lib.agw.aui.auibook.AuiNotebook`. 728 """ 729 730 return self.HasFlag(self.optionNotebookDockable)
731 732
733 - def IsTopSnappable(self):
734 """ Returns ``True`` if the pane can be snapped at the top of the managed frame. """ 735 736 return self.HasFlag(self.optionTopSnapped)
737 738
739 - def IsBottomSnappable(self):
740 """ Returns ``True`` if the pane can be snapped at the bottom of the managed frame. """ 741 742 return self.HasFlag(self.optionBottomSnapped)
743 744
745 - def IsLeftSnappable(self):
746 """ Returns ``True`` if the pane can be snapped on the left of the managed frame. """ 747 748 return self.HasFlag(self.optionLeftSnapped)
749 750
751 - def IsRightSnappable(self):
752 """ Returns ``True`` if the pane can be snapped on the right of the managed frame. """ 753 754 return self.HasFlag(self.optionRightSnapped)
755 756
757 - def IsSnappable(self):
758 """ Returns ``True`` if the pane can be snapped. """ 759 760 return self.IsTopSnappable() or self.IsBottomSnappable() or self.IsLeftSnappable() or \ 761 self.IsRightSnappable()
762 763
764 - def IsFlyOut(self):
765 """ Returns ``True`` if the floating pane has a "fly-out" effect. """ 766 767 return self.HasFlag(self.optionFlyOut)
768 769
770 - def HasCaption(self):
771 """ Returns ``True`` if the pane displays a caption. """ 772 773 return self.HasFlag(self.optionCaption)
774 775
776 - def HasCaptionLeft(self):
777 """ Returns ``True`` if the pane displays a caption on the left (rotated by 90 degrees). """ 778 779 return self.HasFlag(self.optionCaptionLeft)
780 781
782 - def HasGripper(self):
783 """ Returns ``True`` if the pane displays a gripper. """ 784 785 return self.HasFlag(self.optionGripper)
786 787
788 - def HasBorder(self):
789 """ Returns ``True`` if the pane displays a border. """ 790 791 return self.HasFlag(self.optionPaneBorder)
792 793
794 - def HasCloseButton(self):
795 """ Returns ``True`` if the pane displays a button to close the pane. """ 796 797 return self.HasFlag(self.buttonClose)
798 799
800 - def HasMaximizeButton(self):
801 """ Returns ``True`` if the pane displays a button to maximize the pane. """ 802 803 return self.HasFlag(self.buttonMaximize)
804 805
806 - def HasMinimizeButton(self):
807 """ Returns ``True`` if the pane displays a button to minimize the pane. """ 808 809 return self.HasFlag(self.buttonMinimize)
810 811
812 - def GetMinimizeMode(self):
813 """ 814 Returns the minimization style for this pane. 815 816 Possible return values are: 817 818 ============================== ========= ============================== 819 Minimize Mode Flag Hex Value Description 820 ============================== ========= ============================== 821 ``AUI_MINIMIZE_POS_SMART`` 0x01 Minimizes the pane on the closest tool bar 822 ``AUI_MINIMIZE_POS_TOP`` 0x02 Minimizes the pane on the top tool bar 823 ``AUI_MINIMIZE_POS_LEFT`` 0x03 Minimizes the pane on its left tool bar 824 ``AUI_MINIMIZE_POS_RIGHT`` 0x04 Minimizes the pane on its right tool bar 825 ``AUI_MINIMIZE_POS_BOTTOM`` 0x05 Minimizes the pane on its bottom tool bar 826 ``AUI_MINIMIZE_POS_TOOLBAR`` 0x06 Minimizes the pane on a target :class:`~lib.agw.aui.auibar.AuiToolBar` 827 ``AUI_MINIMIZE_POS_MASK`` 0x17 Mask to filter the position flags 828 ``AUI_MINIMIZE_CAPT_HIDE`` 0x0 Hides the caption of the minimized pane 829 ``AUI_MINIMIZE_CAPT_SMART`` 0x08 Displays the caption in the best rotation (horizontal or clockwise) 830 ``AUI_MINIMIZE_CAPT_HORZ`` 0x10 Displays the caption horizontally 831 ``AUI_MINIMIZE_CAPT_MASK`` 0x18 Mask to filter the caption flags 832 ============================== ========= ============================== 833 834 The flags can be filtered with the following masks: 835 836 ============================== ========= ============================== 837 Minimize Mask Flag Hex Value Description 838 ============================== ========= ============================== 839 ``AUI_MINIMIZE_POS_MASK`` 0x17 Filters the position flags 840 ``AUI_MINIMIZE_CAPT_MASK`` 0x18 Filters the caption flags 841 ============================== ========= ============================== 842 843 """ 844 845 return self.minimize_mode
846 847
848 - def HasPinButton(self):
849 """ Returns ``True`` if the pane displays a button to float the pane. """ 850 851 return self.HasFlag(self.buttonPin)
852 853
854 - def HasGripperTop(self):
855 """ Returns ``True`` if the pane displays a gripper at the top. """ 856 857 return self.HasFlag(self.optionGripperTop)
858 859
860 - def Window(self, w):
861 """ 862 Associate a :class:`Window` derived window to this pane. 863 864 This normally does not need to be specified, as the window pointer is 865 automatically assigned to the :class:`AuiPaneInfo` structure as soon as it is 866 added to the manager. 867 868 :param `w`: a :class:`Window` derived window. 869 """ 870 871 self.window = w 872 return self
873 874
875 - def Name(self, name):
876 """ 877 Sets the name of the pane so it can be referenced in lookup functions. 878 879 If a name is not specified by the user, a random name is assigned to the pane 880 when it is added to the manager. 881 882 :param `name`: a string specifying the pane name. 883 884 .. warning:: 885 886 If you are using :meth:`AuiManager.SavePerspective` and :meth:`AuiManager.LoadPerspective`, 887 you will have to specify a name for your pane using :meth:`~AuiPaneInfo.Name`, as perspectives 888 containing randomly generated names can not be properly restored. 889 """ 890 891 self.name = name 892 return self
893 894
895 - def Caption(self, caption):
896 """ 897 Sets the caption of the pane. 898 899 :param string `caption`: a string specifying the pane caption. 900 """ 901 902 self.caption = caption 903 return self
904 905
906 - def Left(self):
907 """ 908 Sets the pane dock position to the left side of the frame. 909 910 :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_LEFT`` as 911 parameter. 912 """ 913 914 self.dock_direction = AUI_DOCK_LEFT 915 return self
916 917
918 - def Right(self):
919 """ 920 Sets the pane dock position to the right side of the frame. 921 922 :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_RIGHT`` as 923 parameter. 924 """ 925 926 self.dock_direction = AUI_DOCK_RIGHT 927 return self
928 929
930 - def Top(self):
931 """ 932 Sets the pane dock position to the top of the frame. 933 934 :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_TOP`` as 935 parameter. 936 """ 937 938 self.dock_direction = AUI_DOCK_TOP 939 return self
940 941
942 - def Bottom(self):
943 """ 944 Sets the pane dock position to the bottom of the frame. 945 946 :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_BOTTOM`` as 947 parameter. 948 """ 949 950 self.dock_direction = AUI_DOCK_BOTTOM 951 return self
952 953
954 - def Center(self):
955 """ 956 Sets the pane to the center position of the frame. 957 958 The centre pane is the space in the middle after all border panes (left, top, 959 right, bottom) are subtracted from the layout. 960 961 :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_CENTER`` as 962 parameter. 963 """ 964 965 self.dock_direction = AUI_DOCK_CENTER 966 return self
967 968
969 - def Centre(self):
970 """ 971 Sets the pane to the center position of the frame. 972 973 The centre pane is the space in the middle after all border panes (left, top, 974 right, bottom) are subtracted from the layout. 975 976 :note: This is the same thing as calling :meth:`~AuiPaneInfo.Direction` with ``AUI_DOCK_CENTRE`` as 977 parameter. 978 """ 979 980 self.dock_direction = AUI_DOCK_CENTRE 981 return self
982 983
984 - def Direction(self, direction):
985 """ 986 Determines the direction of the docked pane. It is functionally the 987 same as calling :meth:`Left`, :meth:`Right`, :meth:`Top` or :meth:`Bottom`, 988 except that docking direction may be specified programmatically via the parameter `direction`. 989 990 :param integer `direction`: the direction of the docked pane. 991 992 :see: :meth:`dock_direction_set` for a list of valid docking directions. 993 """ 994 995 self.dock_direction = direction 996 return self
997 998
999 - def Layer(self, layer):
1000 """ 1001 Determines the layer of the docked pane. 1002 1003 The dock layer is similar to an onion, the inner-most layer being layer 0. Each 1004 shell moving in the outward direction has a higher layer number. This allows for 1005 more complex docking layout formation. 1006 1007 :param integer `layer`: the layer of the docked pane. 1008 """ 1009 1010 self.dock_layer = layer 1011 return self
1012 1013
1014 - def Row(self, row):
1015 """ 1016 Determines the row of the docked pane. 1017 1018 :param integer `row`: the row of the docked pane. 1019 """ 1020 1021 self.dock_row = row 1022 return self
1023 1024
1025 - def Position(self, pos):
1026 """ 1027 Determines the position of the docked pane. 1028 1029 :param integer `pos`: the position of the docked pane. 1030 """ 1031 1032 self.dock_pos = pos 1033 return self
1034 1035
1036 - def MinSize(self, arg1=None, arg2=None):
1037 """ 1038 Sets the minimum size of the pane. 1039 1040 This method is split in 2 versions depending on the input type. If `arg1` is 1041 a :class:`Size` object, then :meth:`~AuiPaneInfo.MinSize1` is called. Otherwise, :meth:`~AuiPaneInfo.MinSize2` is called. 1042 1043 :param `arg1`: a :class:`Size` object, a (x, y) tuple or or a `x` coordinate. 1044 :param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused). 1045 """ 1046 1047 if isinstance(arg1, wx.Size): 1048 ret = self.MinSize1(arg1) 1049 elif isinstance(arg1, types.TupleType): 1050 ret = self.MinSize1(wx.Size(*arg1)) 1051 elif isinstance(arg1, types.IntType) and arg2 is not None: 1052 ret = self.MinSize2(arg1, arg2) 1053 else: 1054 raise Exception("Invalid argument passed to `MinSize`: arg1=%s, arg2=%s"%(repr(arg1), repr(arg2))) 1055 1056 return ret
1057 1058
1059 - def MinSize1(self, size):
1060 """ 1061 Sets the minimum size of the pane. 1062 1063 :see: :meth:`MinSize` for an explanation of input parameters. 1064 """ 1065 self.min_size = size 1066 return self
1067 1068
1069 - def MinSize2(self, x, y):
1070 """ 1071 Sets the minimum size of the pane. 1072 1073 :see: :meth:`MinSize` for an explanation of input parameters. 1074 """ 1075 1076 self.min_size = wx.Size(x, y) 1077 return self
1078 1079
1080 - def MaxSize(self, arg1=None, arg2=None):
1081 """ 1082 Sets the maximum size of the pane. 1083 1084 This method is split in 2 versions depending on the input type. If `arg1` is 1085 a :class:`Size` object, then :meth:`~AuiPaneInfo.MaxSize1` is called. Otherwise, :meth:`~AuiPaneInfo.MaxSize2` is called. 1086 1087 :param `arg1`: a :class:`Size` object, a (x, y) tuple or a `x` coordinate. 1088 :param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused). 1089 """ 1090 1091 if isinstance(arg1, wx.Size): 1092 ret = self.MaxSize1(arg1) 1093 elif isinstance(arg1, types.TupleType): 1094 ret = self.MaxSize1(wx.Size(*arg1)) 1095 elif isinstance(arg1, types.IntType) and arg2 is not None: 1096 ret = self.MaxSize2(arg1, arg2) 1097 else: 1098 raise Exception("Invalid argument passed to `MaxSize`: arg1=%s, arg2=%s"%(repr(arg1), repr(arg2))) 1099 1100 return ret
1101 1102
1103 - def MaxSize1(self, size):
1104 """ 1105 Sets the maximum size of the pane. 1106 1107 :see: :meth:`MaxSize` for an explanation of input parameters. 1108 """ 1109 1110 self.max_size = size 1111 return self
1112 1113
1114 - def MaxSize2(self, x, y):
1115 """ 1116 Sets the maximum size of the pane. 1117 1118 :see: :meth:`MaxSize` for an explanation of input parameters. 1119 """ 1120 1121 self.max_size.Set(x,y) 1122 return self
1123 1124
1125 - def BestSize(self, arg1=None, arg2=None):
1126 """ 1127 Sets the ideal size for the pane. The docking manager will attempt to use 1128 this size as much as possible when docking or floating the pane. 1129 1130 This method is split in 2 versions depending on the input type. If `arg1` is 1131 a :class:`Size` object, then :meth:`BestSize1` is called. Otherwise, :meth:`BestSize2` is called. 1132 1133 :param `arg1`: a :class:`Size` object, a (x, y) tuple or a `x` coordinate. 1134 :param `arg2`: a `y` coordinate (only if `arg1` is a `x` coordinate, otherwise unused). 1135 """ 1136 1137 if isinstance(arg1, wx.Size): 1138 ret = self.BestSize1(arg1) 1139 elif isinstance(arg1, types.TupleType): 1140 ret = self.BestSize1(wx.Size(*arg1)) 1141 elif isinstance(arg1, types.IntType) and arg2 is not None: 1142 ret = self.BestSize2(arg1, arg2) 1143 else: 1144 raise Exception("Invalid argument passed to `BestSize`: arg1=%s, arg2=%s"%(repr(arg1), repr(arg2))) 1145 1146 return ret
1147 1148
1149 - def BestSize1(self, size):
1150 """ 1151 Sets the best size of the pane. 1152 1153 :see: :meth:`BestSize` for an explanation of input parameters. 1154 """ 1155 1156 self.best_size = size 1157 return self
1158 1159
1160 - def BestSize2(self, x, y):
1161 """ 1162 Sets the best size of the pane. 1163 1164 :see: :meth:`BestSize` for an explanation of input parameters. 1165 """ 1166 1167 self.best_size.Set(x,y) 1168 return self
1169 1170
1171 - def FloatingPosition(self, pos):
1172 """ 1173 Sets the position of the floating pane. 1174 1175 :param `pos`: a :class:`Point` or a tuple indicating the pane floating position. 1176 """ 1177 1178 self.floating_pos = wx.Point(*pos) 1179 return self
1180 1181
1182 - def FloatingSize(self, size):
1183 """ 1184 Sets the size of the floating pane. 1185 1186 :param `size`: a :class:`Size` or a tuple indicating the pane floating size. 1187 """ 1188 1189 self.floating_size = wx.Size(*size) 1190 return self
1191 1192
1193 - def Maximize(self):
1194 """ Makes the pane take up the full area.""" 1195 1196 return self.SetFlag(self.optionMaximized, True)
1197 1198
1199 - def Minimize(self):
1200 """ 1201 Makes the pane minimized in a :class:`~lib.agw.aui.auibar.AuiToolBar`. 1202 1203 Clicking on the minimize button causes a new :class:`~lib.agw.aui.auibar.AuiToolBar` to be created 1204 and added to the frame manager, (currently the implementation is such that 1205 panes at West will have a toolbar at the right, panes at South will have 1206 toolbars at the bottom etc...) and the pane is hidden in the manager. 1207 1208 Clicking on the restore button on the newly created toolbar will result in the 1209 toolbar being removed and the original pane being restored. 1210 """ 1211 1212 return self.SetFlag(self.optionMinimized, True)
1213 1214
1215 - def MinimizeMode(self, mode):
1216 """ 1217 Sets the expected minimized mode if the minimize button is visible. 1218 1219 :param integer `mode`: the minimized pane can have a specific position in the work space: 1220 1221 ============================== ========= ============================== 1222 Minimize Mode Flag Hex Value Description 1223 ============================== ========= ============================== 1224 ``AUI_MINIMIZE_POS_SMART`` 0x01 Minimizes the pane on the closest tool bar 1225 ``AUI_MINIMIZE_POS_TOP`` 0x02 Minimizes the pane on the top tool bar 1226 ``AUI_MINIMIZE_POS_LEFT`` 0x03 Minimizes the pane on its left tool bar 1227 ``AUI_MINIMIZE_POS_RIGHT`` 0x04 Minimizes the pane on its right tool bar 1228 ``AUI_MINIMIZE_POS_BOTTOM`` 0x05 Minimizes the pane on its bottom tool bar 1229 ``AUI_MINIMIZE_POS_TOOLBAR`` 0x06 Minimizes the pane on a target :class:`~lib.agw.aui.auibar.AuiToolBar` 1230 ============================== ========= ============================== 1231 1232 The caption of the minimized pane can be displayed in different modes: 1233 1234 ============================== ========= ============================== 1235 Caption Mode Flag Hex Value Description 1236 ============================== ========= ============================== 1237 ``AUI_MINIMIZE_CAPT_HIDE`` 0x0 Hides the caption of the minimized pane 1238 ``AUI_MINIMIZE_CAPT_SMART`` 0x08 Displays the caption in the best rotation (horizontal in the top and in 1239 the bottom tool bar or clockwise in the right and in the left tool bar) 1240 ``AUI_MINIMIZE_CAPT_HORZ`` 0x10 Displays the caption horizontally 1241 ============================== ========= ============================== 1242 1243 .. note:: 1244 1245 In order to use the ``AUI_MINIMIZE_POS_TOOLBAR`` flag, the instance of :class:`AuiManager` 1246 you pass as an input for :meth:`MinimizeTarget` **must** have a real name and not the randomly 1247 generated one. Remember to set the :meth:`Name` property of the toolbar pane before calling this method. 1248 1249 """ 1250 1251 self.minimize_mode = mode 1252 return self
1253 1254
1255 - def MinimizeTarget(self, toolbarPane):
1256 """ 1257 Minimizes the panes using a :class:`AuiPaneInfo` as a target. As :class:`AuiPaneInfo` properties 1258 need to be copied back and forth every time the perspective has changed, we 1259 only store the toobar **name**. 1260 1261 :param `toolbarPane`: an instance of :class:`AuiPaneInfo`, containing a :class:`~lib.agw.aui.auibar.AuiToolBar`. 1262 1263 .. note:: 1264 1265 In order to use this functionality (and with the ``AUI_MINIMIZE_POS_TOOLBAR`` 1266 flag set), the instance of :class:`AuiPaneInfo` you pass as an input **must** have a real 1267 name and not the randomly generated one. Remember to set the :meth:`Name` property of 1268 the toolbar pane before calling this method. 1269 1270 """ 1271 1272 self.minimize_target = toolbarPane.name 1273 return self
1274 1275
1276 - def Restore(self):
1277 """ Is the reverse of :meth:`Maximize` and :meth:`Minimize`.""" 1278 1279 return self.SetFlag(self.optionMaximized or self.optionMinimized, False)
1280 1281
1282 - def Fixed(self):
1283 """ 1284 Forces a pane to be fixed size so that it cannot be resized. 1285 After calling :meth:`Fixed`, :meth:`IsFixed` will return ``True``. 1286 """ 1287 1288 return self.SetFlag(self.optionResizable, False)
1289 1290
1291 - def Resizable(self, resizable=True):
1292 """ 1293 Allows a pane to be resizable if `resizable` is ``True``, and forces 1294 it to be a fixed size if `resizeable` is ``False``. 1295 1296 If `resizable` is ``False``, this is simply an antonym for :meth:`Fixed`. 1297 1298 :param bool `resizable`: whether the pane will be resizeable or not. 1299 """ 1300 1301 return self.SetFlag(self.optionResizable, resizable)
1302 1303
1304 - def Transparent(self, alpha):
1305 """ 1306 Makes the pane transparent when floating. 1307 1308 :param integer `alpha`: a value between 0 and 255 for pane transparency. 1309 """ 1310 1311 if alpha < 0 or alpha > 255: 1312 raise Exception("Invalid transparency value (%s)"%repr(alpha)) 1313 1314 self.transparent = alpha 1315 self.needsTransparency = True
1316 1317
1318 - def Dock(self):
1319 """ Indicates that a pane should be docked. It is the opposite of :meth:`Float`. """ 1320 1321 if self.IsNotebookPage(): 1322 self.notebook_id = -1 1323 self.dock_direction = AUI_DOCK_NONE 1324 1325 return self.SetFlag(self.optionFloating, False)
1326 1327
1328 - def Float(self):
1329 """ Indicates that a pane should be floated. It is the opposite of :meth:`Dock`. """ 1330 1331 if self.IsNotebookPage(): 1332 self.notebook_id = -1 1333 self.dock_direction = AUI_DOCK_NONE 1334 1335 return self.SetFlag(self.optionFloating, True)
1336 1337
1338 - def Hide(self):
1339 """ 1340 Indicates that a pane should be hidden. 1341 1342 Calling :meth:`Show(False) <Show>` achieve the same effect. 1343 """ 1344 1345 return self.SetFlag(self.optionHidden, True)
1346 1347
1348 - def Show(self, show=True):
1349 """ 1350 Indicates that a pane should be shown. 1351 1352 :param bool `show`: whether the pane should be shown or not. 1353 """ 1354 1355 return self.SetFlag(self.optionHidden, not show)
1356 1357 1358 # By defaulting to 1000, the tab will get placed at the end
1359 - def NotebookPage(self, id, tab_position=1000):
1360 """ 1361 Forces a pane to be a notebook page, so that the pane can be 1362 docked on top to another to create a :class:`~lib.agw.aui.auibook.AuiNotebook`. 1363 1364 :param integer `id`: the notebook id; 1365 :param integer `tab_position`: the tab number of the pane once docked in a notebook. 1366 """ 1367 1368 # Remove any floating frame 1369 self.Dock() 1370 self.notebook_id = id 1371 self.dock_pos = tab_position 1372 self.dock_row = 0 1373 self.dock_layer = 0 1374 self.dock_direction = AUI_DOCK_NOTEBOOK_PAGE 1375 1376 return self
1377 1378
1379 - def NotebookControl(self, id):
1380 """ 1381 Forces a pane to be a notebook control (:class:`~lib.agw.aui.auibook.AuiNotebook`). 1382 1383 :param integer `id`: the notebook id. 1384 """ 1385 1386 self.notebook_id = id 1387 self.window = None 1388 self.buttons = [] 1389 1390 if self.dock_direction == AUI_DOCK_NOTEBOOK_PAGE: 1391 self.dock_direction = AUI_DOCK_NONE 1392 1393 return self
1394 1395
1396 - def HasNotebook(self):
1397 """ Returns whether a pane has a :class:`~lib.agw.aui.auibook.AuiNotebook` or not. """ 1398 1399 return self.notebook_id >= 0
1400 1401
1402 - def IsNotebookPage(self):
1403 """ Returns whether the pane is a notebook page in a :class:`~lib.agw.aui.auibook.AuiNotebook`. """ 1404 1405 return self.notebook_id >= 0 and self.dock_direction == AUI_DOCK_NOTEBOOK_PAGE
1406 1407
1408 - def IsNotebookControl(self):
1409 """ Returns whether the pane is a notebook control (:class:`~lib.agw.aui.auibook.AuiNotebook`). """ 1410 1411 return not self.IsNotebookPage() and self.HasNotebook()
1412 1413
1414 - def SetNameFromNotebookId(self):
1415 """ Sets the pane name once docked in a :class:`~lib.agw.aui.auibook.AuiNotebook` using the notebook id. """ 1416 1417 if self.notebook_id >= 0: 1418 self.name = "__notebook_%d"%self.notebook_id 1419 1420 return self
1421 1422
1423 - def CaptionVisible(self, visible=True, left=False):
1424 """ 1425 Indicates that a pane caption should be visible. If `visible` is ``False``, no pane 1426 caption is drawn. 1427 1428 :param bool `visible`: whether the caption should be visible or not; 1429 :param bool `left`: whether the caption should be drawn on the left (rotated by 90 degrees) or not. 1430 """ 1431 1432 if left: 1433 self.SetFlag(self.optionCaption, False) 1434 return self.SetFlag(self.optionCaptionLeft, visible) 1435 1436 self.SetFlag(self.optionCaptionLeft, False) 1437 return self.SetFlag(self.optionCaption, visible)
1438 1439
1440 - def PaneBorder(self, visible=True):
1441 """ 1442 Indicates that a border should be drawn for the pane. 1443 1444 :param bool `visible`: whether the pane border should be visible or not. 1445 """ 1446 1447 return self.SetFlag(self.optionPaneBorder, visible)
1448 1449
1450 - def Gripper(self, visible=True):
1451 """ 1452 Indicates that a gripper should be drawn for the pane. 1453 1454 :param bool `visible`: whether the gripper should be visible or not. 1455 """ 1456 1457 return self.SetFlag(self.optionGripper, visible)
1458 1459
1460 - def GripperTop(self, attop=True):
1461 """ 1462 Indicates that a gripper should be drawn at the top of the pane. 1463 1464 :param bool `attop`: whether the gripper should be drawn at the top or not. 1465 """ 1466 1467 return self.SetFlag(self.optionGripperTop, attop)
1468 1469
1470 - def CloseButton(self, visible=True):
1471 """ 1472 Indicates that a close button should be drawn for the pane. 1473 1474 :param bool `visible`: whether the close button should be visible or not. 1475 """ 1476 1477 return self.SetFlag(self.buttonClose, visible)
1478 1479
1480 - def MaximizeButton(self, visible=True):
1481 """ 1482 Indicates that a maximize button should be drawn for the pane. 1483 1484 :param bool `visible`: whether the maximize button should be visible or not. 1485 """ 1486 1487 return self.SetFlag(self.buttonMaximize, visible)
1488 1489
1490 - def MinimizeButton(self, visible=True):
1491 """ 1492 Indicates that a minimize button should be drawn for the pane. 1493 1494 :param bool `visible`: whether the minimize button should be visible or not. 1495 """ 1496 1497 return self.SetFlag(self.buttonMinimize, visible)
1498 1499
1500 - def PinButton(self, visible=True):
1501 """ 1502 Indicates that a pin button should be drawn for the pane. 1503 1504 :param bool `visible`: whether the pin button should be visible or not. 1505 """ 1506 1507 return self.SetFlag(self.buttonPin, visible)
1508 1509
1510 - def DestroyOnClose(self, b=True):
1511 """ 1512 Indicates whether a pane should be destroyed when it is closed. 1513 1514 Normally a pane is simply hidden when the close button is clicked. Setting 1515 `b` to ``True`` will cause the window to be destroyed when the user clicks 1516 the pane's close button. 1517 1518 :param bool `b`: whether the pane should be destroyed when it is closed or not. 1519 """ 1520 1521 return self.SetFlag(self.optionDestroyOnClose, b)
1522 1523
1524 - def TopDockable(self, b=True):
1525 """ 1526 Indicates whether a pane can be docked at the top of the frame. 1527 1528 :param bool `b`: whether the pane can be docked at the top or not. 1529 """ 1530 1531 return self.SetFlag(self.optionTopDockable, b)
1532 1533
1534 - def BottomDockable(self, b=True):
1535 """ 1536 Indicates whether a pane can be docked at the bottom of the frame. 1537 1538 :param bool `b`: whether the pane can be docked at the bottom or not. 1539 """ 1540 1541 return self.SetFlag(self.optionBottomDockable, b)
1542 1543
1544 - def LeftDockable(self, b=True):
1545 """ 1546 Indicates whether a pane can be docked on the left of the frame. 1547 1548 :param bool `b`: whether the pane can be docked at the left or not. 1549 """ 1550 1551 return self.SetFlag(self.optionLeftDockable, b)
1552 1553
1554 - def RightDockable(self, b=True):
1555 """ 1556 Indicates whether a pane can be docked on the right of the frame. 1557 1558 :param bool `b`: whether the pane can be docked at the right or not. 1559 """ 1560 1561 return self.SetFlag(self.optionRightDockable, b)
1562 1563
1564 - def Floatable(self, b=True):
1565 """ 1566 Sets whether the user will be able to undock a pane and turn it 1567 into a floating window. 1568 1569 :param bool `b`: whether the pane can be floated or not. 1570 """ 1571 1572 return self.SetFlag(self.optionFloatable, b)
1573 1574
1575 - def Movable(self, b=True):
1576 """ 1577 Indicates whether a pane can be moved. 1578 1579 :param bool `b`: whether the pane can be moved or not. 1580 """ 1581 1582 return self.SetFlag(self.optionMovable, b)
1583 1584
1585 - def NotebookDockable(self, b=True):
1586 """ 1587 Indicates whether a pane can be docked in an automatic :class:`~lib.agw.aui.auibook.AuiNotebook`. 1588 1589 :param bool `b`: whether the pane can be docked in a notebook or not. 1590 """ 1591 1592 return self.SetFlag(self.optionNotebookDockable, b)
1593 1594
1595 - def DockFixed(self, b=True):
1596 """ 1597 Causes the containing dock to have no resize sash. This is useful 1598 for creating panes that span the entire width or height of a dock, but should 1599 not be resizable in the other direction. 1600 1601 :param bool `b`: whether the pane will have a resize sash or not. 1602 """ 1603 1604 return self.SetFlag(self.optionDockFixed, b)
1605 1606
1607 - def Dockable(self, b=True):
1608 """ 1609 Specifies whether a frame can be docked or not. It is the same as specifying 1610 :meth:`TopDockable` . :meth:`BottomDockable` . :meth:`LeftDockable` . :meth:`RightDockable` . 1611 1612 :param bool `b`: whether the frame can be docked or not. 1613 """ 1614 1615 return self.TopDockable(b).BottomDockable(b).LeftDockable(b).RightDockable(b)
1616 1617
1618 - def TopSnappable(self, b=True):
1619 """ 1620 Indicates whether a pane can be snapped at the top of the main frame. 1621 1622 :param bool `b`: whether the pane can be snapped at the top of the main frame or not. 1623 """ 1624 1625 return self.SetFlag(self.optionTopSnapped, b)
1626 1627
1628 - def BottomSnappable(self, b=True):
1629 """ 1630 Indicates whether a pane can be snapped at the bottom of the main frame. 1631 1632 :param bool `b`: whether the pane can be snapped at the bottom of the main frame or not. 1633 """ 1634 1635 return self.SetFlag(self.optionBottomSnapped, b)
1636 1637
1638 - def LeftSnappable(self, b=True):
1639 """ 1640 Indicates whether a pane can be snapped on the left of the main frame. 1641 1642 :param bool `b`: whether the pane can be snapped at the left of the main frame or not. 1643 """ 1644 1645 return self.SetFlag(self.optionLeftSnapped, b)
1646 1647
1648 - def RightSnappable(self, b=True):
1649 """ 1650 Indicates whether a pane can be snapped on the right of the main frame. 1651 1652 :param bool `b`: whether the pane can be snapped at the right of the main frame or not. 1653 """ 1654 1655 return self.SetFlag(self.optionRightSnapped, b)
1656 1657
1658 - def Snappable(self, b=True):
1659 """ 1660 Indicates whether a pane can be snapped on the main frame. This is 1661 equivalent as calling :meth:`TopSnappable` . :meth:`BottomSnappable` . :meth:`LeftSnappable` . :meth:`RightSnappable` . 1662 1663 :param bool `b`: whether the pane can be snapped on the main frame or not. 1664 """ 1665 1666 return self.TopSnappable(b).BottomSnappable(b).LeftSnappable(b).RightSnappable(b)
1667 1668
1669 - def FlyOut(self, b=True):
1670 """ 1671 Indicates whether a pane, when floating, has a "fly-out" effect 1672 (i.e., floating panes which only show themselves when moused over). 1673 1674 :param bool `b`: whether the pane can be snapped on the main frame or not. 1675 """ 1676 1677 return self.SetFlag(self.optionFlyOut, b)
1678 1679 1680 # Copy over the members that pertain to docking position
1681 - def SetDockPos(self, source):
1682 """ 1683 Copies the `source` pane members that pertain to docking position to `self`. 1684 1685 :param AuiPaneInfo `source`: the source pane from where to copy the attributes. 1686 """ 1687 1688 self.dock_direction = source.dock_direction 1689 self.dock_layer = source.dock_layer 1690 self.dock_row = source.dock_row 1691 self.dock_pos = source.dock_pos 1692 self.dock_proportion = source.dock_proportion 1693 self.floating_pos = wx.Point(*source.floating_pos) 1694 self.floating_size = wx.Size(*source.floating_size) 1695 self.rect = wx.Rect(*source.rect) 1696 1697 return self
1698 1699
1700 - def DefaultPane(self):
1701 """ Specifies that the pane should adopt the default pane settings. """ 1702 1703 state = self.state 1704 state |= self.optionTopDockable | self.optionBottomDockable | \ 1705 self.optionLeftDockable | self.optionRightDockable | \ 1706 self.optionNotebookDockable | \ 1707 self.optionFloatable | self.optionMovable | self.optionResizable | \ 1708 self.optionCaption | self.optionPaneBorder | self.buttonClose 1709 1710 self.state = state 1711 return self
1712 1713
1714 - def CentrePane(self):
1715 """ 1716 Specifies that the pane should adopt the default center pane settings. 1717 1718 Centre panes usually do not have caption bars. This function provides an easy way of 1719 preparing a pane to be displayed in the center dock position. 1720 """ 1721 1722 return self.CenterPane()
1723 1724
1725 - def CenterPane(self):
1726 """ 1727 Specifies that the pane should adopt the default center pane settings. 1728 1729 Centre panes usually do not have caption bars. This function provides an easy way of 1730 preparing a pane to be displayed in the center dock position. 1731 """ 1732 1733 self.state = 0 1734 return self.Center().PaneBorder().Resizable()
1735 1736
1737 - def ToolbarPane(self):
1738 """ Specifies that the pane should adopt the default toolbar pane settings. """ 1739 1740 self.DefaultPane() 1741 state = self.state 1742 1743 state |= (self.optionToolbar | self.optionGripper) 1744 state &= ~(self.optionResizable | self.optionCaption | self.optionCaptionLeft) 1745 1746 if self.dock_layer == 0: 1747 self.dock_layer = 10 1748 1749 self.state = state 1750 1751 return self
1752 1753
1754 - def Icon(self, icon):
1755 """ 1756 Specifies whether an icon is drawn on the left of the caption text when 1757 the pane is docked. If `icon` is ``None`` or :class:`NullIcon`, no icon is drawn on 1758 the caption space. 1759 1760 :param icon: an icon to draw on the caption space, or ``None``. 1761 :type `icon`: :class:`Icon` or ``None`` 1762 """ 1763 1764 if icon is None: 1765 icon = wx.NullIcon 1766 1767 self.icon = icon 1768 return self
1769 1770
1771 - def SetFlag(self, flag, option_state):
1772 """ 1773 Turns the property given by `flag` on or off with the `option_state` 1774 parameter. 1775 1776 :param integer `flag`: the property to set; 1777 :param bool `option_state`: either ``True`` or ``False``. 1778 """ 1779 1780 state = self.state 1781 1782 if option_state: 1783 state |= flag 1784 else: 1785 state &= ~flag 1786 1787 self.state = state 1788 1789 if flag in [self.buttonClose, self.buttonMaximize, self.buttonMinimize, self.buttonPin]: 1790 self.ResetButtons() 1791 1792 return self
1793 1794
1795 - def HasFlag(self, flag):
1796 """ 1797 Returns ``True`` if the the property specified by flag is active for the pane. 1798 1799 :param integer `flag`: the property to check for activity. 1800 """ 1801 1802 return (self.state & flag and [True] or [False])[0]
1803 1804
1805 - def ResetButtons(self):
1806 """ 1807 Resets all the buttons and recreates them from scratch depending on the 1808 :class:`AuiManager` flags. 1809 """ 1810 1811 floating = self.HasFlag(self.optionFloating) 1812 self.buttons = [] 1813 1814 if not floating and self.HasMinimizeButton(): 1815 button = AuiPaneButton(AUI_BUTTON_MINIMIZE) 1816 self.buttons.append(button) 1817 1818 if not floating and self.HasMaximizeButton(): 1819 button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE) 1820 self.buttons.append(button) 1821 1822 if not floating and self.HasPinButton(): 1823 button = AuiPaneButton(AUI_BUTTON_PIN) 1824 self.buttons.append(button) 1825 1826 if self.HasCloseButton(): 1827 button = AuiPaneButton(AUI_BUTTON_CLOSE) 1828 self.buttons.append(button)
1829 1830
1831 - def CountButtons(self):
1832 """ Returns the number of visible buttons in the docked pane. """ 1833 1834 n = 0 1835 1836 if self.HasCaption() or self.HasCaptionLeft(): 1837 if isinstance(wx.GetTopLevelParent(self.window), AuiFloatingFrame): 1838 return 1 1839 1840 if self.HasCloseButton(): 1841 n += 1 1842 if self.HasMaximizeButton(): 1843 n += 1 1844 if self.HasMinimizeButton(): 1845 n += 1 1846 if self.HasPinButton(): 1847 n += 1 1848 1849 return n
1850 1851
1852 - def IsHorizontal(self):
1853 """ Returns ``True`` if the pane `dock_direction` is horizontal. """ 1854 1855 return self.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]
1856
1857 - def IsVertical(self):
1858 """ Returns ``True`` if the pane `dock_direction` is vertical. """ 1859 1860 return self.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT]
1861 1862 1863 # Null AuiPaneInfo reference 1864 NonePaneInfo = AuiPaneInfo() 1865 """ Null :class:`AuiPaneInfo` reference, an invalid instance of :class:`AuiPaneInfo`. """ 1866 1867 1868 # ---------------------------------------------------------------------------- # 1869
1870 -class AuiDockingGuide(wx.Frame):
1871 """ Base class for :class:`AuiSingleDockingGuide` and :class:`AuiCenterDockingGuide`.""" 1872
1873 - def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition, 1874 size=wx.DefaultSize, style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP | 1875 wx.FRAME_NO_TASKBAR | wx.NO_BORDER, name="AuiDockingGuide"):
1876 """ 1877 Default class constructor. Used internally, do not call it in your code! 1878 1879 :param `parent`: the :class:`AuiManager` parent; 1880 :param integer `id`: the window identifier. It may take a value of -1 to indicate a default value. 1881 :param string `title`: the caption to be displayed on the frame's title bar. 1882 :param Point `pos`: the window position. A value of (-1, -1) indicates a default position, 1883 chosen by either the windowing system or wxPython, depending on platform. 1884 :param Size `size`: the window size. A value of (-1, -1) indicates a default size, chosen by 1885 either the windowing system or wxPython, depending on platform. 1886 :param integer `style`: the window style. 1887 :param string `name`: the name of the window. This parameter is used to associate a name with the 1888 item, allowing the application user to set Motif resource values for individual windows. 1889 """ 1890 1891 wx.Frame.__init__(self, parent, id, title, pos, size, style, name=name)
1892 1893
1894 - def HitTest(self, x, y):
1895 """ 1896 To be overridden by parent classes. 1897 1898 :param integer `x`: the `x` mouse position; 1899 :param integer `y`: the `y` mouse position. 1900 """ 1901 1902 return 0
1903 1904
1905 - def ValidateNotebookDocking(self, valid):
1906 """ 1907 To be overridden by parent classes. 1908 1909 :param bool `valid`: whether a pane can be docked on top to another to form an automatic 1910 :class:`~lib.agw.aui.auibook.AuiNotebook`. 1911 """ 1912 1913 return 0
1914 1915 # ============================================================================ 1916 # implementation 1917 # ============================================================================ 1918 1919 # --------------------------------------------------------------------------- 1920 # AuiDockingGuideWindow 1921 # --------------------------------------------------------------------------- 1922
1923 -class AuiDockingGuideWindow(wx.Window):
1924 """ Target class for :class:`AuiDockingGuide` and :class:`AuiCenterDockingGuide`. """ 1925
1926 - def __init__(self, parent, rect, direction=0, center=False, useAero=False):
1927 """ 1928 Default class constructor. Used internally, do not call it in your code! 1929 1930 :param `parent`: the :class:`AuiManager` parent; 1931 :param Rect `rect`: the window rect; 1932 :param integer `direction`: one of ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, ``wx.RIGHT``, 1933 ``wx.CENTER``; 1934 :param bool `center`: whether the calling class is a :class:`AuiCenterDockingGuide`; 1935 :param bool `useAero`: whether to use the new Aero-style bitmaps or Whidbey-style bitmaps 1936 for the docking guide. 1937 """ 1938 1939 wx.Window.__init__(self, parent, -1, rect.GetPosition(), rect.GetSize(), wx.NO_BORDER) 1940 1941 self._direction = direction 1942 self._center = center 1943 self._valid = True 1944 self._useAero = useAero 1945 1946 self._bmp_unfocus, self._bmp_focus = GetDockingImage(direction, useAero, center) 1947 1948 self._currentImage = self._bmp_unfocus 1949 self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) 1950 1951 self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) 1952 self.Bind(wx.EVT_PAINT, self.OnPaint)
1953 1954
1955 - def SetValid(self, valid):
1956 """ 1957 Sets the docking direction as valid or invalid. 1958 1959 :param bool `valid`: whether the docking direction is allowed or not. 1960 """ 1961 1962 self._valid = valid
1963 1964
1965 - def IsValid(self):
1966 """ Returns whether the docking direction is valid. """ 1967 1968 return self._valid
1969 1970
1971 - def OnEraseBackground(self, event):
1972 """ 1973 Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiDockingGuideWindow`. 1974 1975 :param `event`: a :class:`EraseEvent` to be processed. 1976 1977 :note: This is intentionally empty to reduce flickering while drawing. 1978 """ 1979 1980 pass
1981 1982
1983 - def DrawBackground(self, dc):
1984 """ 1985 Draws the docking guide background. 1986 1987 :param `dc`: a :class:`DC` device context object. 1988 """ 1989 1990 rect = self.GetClientRect() 1991 1992 dc.SetPen(wx.TRANSPARENT_PEN) 1993 dc.SetBrush(wx.Brush(colourTargetBackground)) 1994 dc.DrawRectangleRect(rect) 1995 1996 dc.SetPen(wx.Pen(colourTargetBorder)) 1997 1998 left = rect.GetLeft() 1999 top = rect.GetTop() 2000 right = rect.GetRight() 2001 bottom = rect.GetBottom() 2002 2003 if self._direction != wx.CENTER: 2004 2005 if not self._center or self._direction != wx.BOTTOM: 2006 dc.DrawLine(left, top, right+1, top) 2007 if not self._center or self._direction != wx.RIGHT: 2008 dc.DrawLine(left, top, left, bottom+1) 2009 if not self._center or self._direction != wx.LEFT: 2010 dc.DrawLine(right, top, right, bottom+1) 2011 if not self._center or self._direction != wx.TOP: 2012 dc.DrawLine(left, bottom, right+1, bottom) 2013 2014 dc.SetPen(wx.Pen(colourTargetShade)) 2015 2016 if self._direction != wx.RIGHT: 2017 dc.DrawLine(left + 1, top + 1, left + 1, bottom) 2018 if self._direction != wx.BOTTOM: 2019 dc.DrawLine(left + 1, top + 1, right, top + 1)
2020 2021
2022 - def DrawDottedLine(self, dc, point, length, vertical):
2023 """ 2024 Draws a dotted line (not used if the docking guide images are ok). 2025 2026 :param `dc`: a :class:`DC` device context object; 2027 :param `point`: a :class:`Point` where to start drawing the dotted line; 2028 :param integer `length`: the length of the dotted line; 2029 :param bool `vertical`: whether it is a vertical docking guide window or not. 2030 """ 2031 2032 for i in xrange(0, length, 2): 2033 dc.DrawPoint(point.x, point.y) 2034 if vertical: 2035 point.y += 2 2036 else: 2037 point.x += 2
2038 2039
2040 - def DrawIcon(self, dc):
2041 """ 2042 Draws the docking guide icon (not used if the docking guide images are ok). 2043 2044 :param `dc`: a :class:`DC` device context object. 2045 """ 2046 2047 rect = wx.Rect(*self.GetClientRect()) 2048 point = wx.Point() 2049 length = 0 2050 2051 rect.Deflate(4, 4) 2052 dc.SetPen(wx.Pen(colourIconBorder)) 2053 dc.SetBrush(wx.Brush(colourIconBackground)) 2054 dc.DrawRectangleRect(rect) 2055 2056 right1 = rect.GetRight() + 1 2057 bottom1 = rect.GetBottom() + 1 2058 2059 dc.SetPen(wx.Pen(colourIconShadow)) 2060 dc.DrawLine(rect.x + 1, bottom1, right1 + 1, bottom1) 2061 dc.DrawLine(right1, rect.y + 1, right1, bottom1 + 1) 2062 2063 rect.Deflate(1, 1) 2064 2065 if self._direction == wx.TOP: 2066 rect.height -= rect.height / 2 2067 point = rect.GetBottomLeft() 2068 length = rect.width 2069 2070 elif self._direction == wx.LEFT: 2071 rect.width -= rect.width / 2 2072 point = rect.GetTopRight() 2073 length = rect.height 2074 2075 elif self._direction == wx.RIGHT: 2076 rect.x += rect.width / 2 2077 rect.width -= rect.width / 2 2078 point = rect.GetTopLeft() 2079 length = rect.height 2080 2081 elif self._direction == wx.BOTTOM: 2082 rect.y += rect.height / 2 2083 rect.height -= rect.height / 2 2084 point = rect.GetTopLeft() 2085 length = rect.width 2086 2087 elif self._direction == wx.CENTER: 2088 rect.Deflate(1, 1) 2089 point = rect.GetTopLeft() 2090 length = rect.width 2091 2092 dc.GradientFillLinear(rect, colourIconDockingPart1, 2093 colourIconDockingPart2, self._direction) 2094 2095 dc.SetPen(wx.Pen(colourIconBorder)) 2096 2097 if self._direction == wx.CENTER: 2098 self.DrawDottedLine(dc, rect.GetTopLeft(), rect.width, False) 2099 self.DrawDottedLine(dc, rect.GetTopLeft(), rect.height, True) 2100 self.DrawDottedLine(dc, rect.GetBottomLeft(), rect.width, False) 2101 self.DrawDottedLine(dc, rect.GetTopRight(), rect.height, True) 2102 2103 elif self._direction in [wx.TOP, wx.BOTTOM]: 2104 self.DrawDottedLine(dc, point, length, False) 2105 2106 else: 2107 self.DrawDottedLine(dc, point, length, True)
2108 2109
2110 - def DrawArrow(self, dc):
2111 """ 2112 Draws the docking guide arrow icon (not used if the docking guide images are ok). 2113 2114 :param `dc`: a :class:`DC` device context object. 2115 """ 2116 2117 rect = self.GetClientRect() 2118 point = wx.Point() 2119 2120 point.x = (rect.GetLeft() + rect.GetRight()) / 2 2121 point.y = (rect.GetTop() + rect.GetBottom()) / 2 2122 rx, ry = wx.Size(), wx.Size() 2123 2124 if self._direction == wx.TOP: 2125 rx = wx.Size(1, 0) 2126 ry = wx.Size(0, 1) 2127 2128 elif self._direction == wx.LEFT: 2129 rx = wx.Size(0, -1) 2130 ry = wx.Size(1, 0) 2131 2132 elif self._direction == wx.RIGHT: 2133 rx = wx.Size(0, 1) 2134 ry = wx.Size(-1, 0) 2135 2136 elif self._direction == wx.BOTTOM: 2137 rx = wx.Size(-1, 0) 2138 ry = wx.Size(0, -1) 2139 2140 point.x += ry.x*3 2141 point.y += ry.y*3 2142 2143 dc.SetPen(wx.Pen(colourIconArrow)) 2144 2145 for i in xrange(4): 2146 pt1 = wx.Point(point.x - rx.x*i, point.y - rx.y*i) 2147 pt2 = wx.Point(point.x + rx.x*(i+1), point.y + rx.y*(i+1)) 2148 dc.DrawLinePoint(pt1, pt2) 2149 point.x += ry.x 2150 point.y += ry.y
2151 2152
2153 - def OnPaint(self, event):
2154 """ 2155 Handles the ``wx.EVT_PAINT`` event for :class:`AuiDockingGuideWindow`. 2156 2157 :param `event`: a :class:`PaintEvent` to be processed. 2158 """ 2159 2160 dc = wx.AutoBufferedPaintDC(self) 2161 if self._currentImage.IsOk() and self._valid: 2162 dc.DrawBitmap(self._currentImage, 0, 0, True) 2163 else: 2164 self.Draw(dc)
2165 2166
2167 - def Draw(self, dc):
2168 """ 2169 Draws the whole docking guide window (not used if the docking guide images are ok). 2170 2171 :param `dc`: a :class:`DC` device context object. 2172 """ 2173 2174 self.DrawBackground(dc) 2175 2176 if self._valid: 2177 self.DrawIcon(dc) 2178 self.DrawArrow(dc)
2179 2180
2181 - def UpdateDockGuide(self, pos):
2182 """ 2183 Updates the docking guide images depending on the mouse position, using focused 2184 images if the mouse is inside the docking guide or unfocused images if it is 2185 outside. 2186 2187 :param `pos`: a :class:`Point` mouse position. 2188 """ 2189 2190 inside = self.GetScreenRect().Contains(pos) 2191 2192 if inside: 2193 image = self._bmp_focus 2194 else: 2195 image = self._bmp_unfocus 2196 2197 if image != self._currentImage: 2198 self._currentImage = image 2199 self.Refresh() 2200 self.Update()
2201 2202 2203 # --------------------------------------------------------------------------- 2204 # AuiSingleDockingGuide 2205 # --------------------------------------------------------------------------- 2206
2207 -class AuiSingleDockingGuide(AuiDockingGuide):
2208 """ A docking guide window for single docking hint (not diamond-shaped HUD). """ 2209
2210 - def __init__(self, parent, direction=0):
2211 """ 2212 Default class constructor. Used internally, do not call it in your code! 2213 2214 :param `parent`: the :class:`AuiManager` parent; 2215 :param integer `direction`: one of ``wx.TOP``, ``wx.BOTTOM``, ``wx.LEFT``, ``wx.RIGHT``. 2216 """ 2217 2218 self._direction = direction 2219 2220 style = wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP | \ 2221 wx.FRAME_NO_TASKBAR | wx.NO_BORDER 2222 2223 # Use of FRAME_SHAPED on wxMac causes the frame to be visible 2224 # breaking the docking hints. 2225 if wx.Platform != '__WXMAC__': 2226 style |= wx.FRAME_SHAPED 2227 2228 AuiDockingGuide.__init__(self, parent, style=style, name="auiSingleDockTarget") 2229 2230 self.Hide() 2231 2232 useAero = GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_AERO_DOCKING_GUIDES 2233 useWhidbey = GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES 2234 2235 self._useAero = useAero or useWhidbey 2236 self._valid = True 2237 2238 if useAero: 2239 sizeX, sizeY = aeroguideSizeX, aeroguideSizeY 2240 elif useWhidbey: 2241 sizeX, sizeY = whidbeySizeX, whidbeySizeY 2242 else: 2243 sizeX, sizeY = guideSizeX, guideSizeY 2244 2245 if direction not in [wx.TOP, wx.BOTTOM]: 2246 sizeX, sizeY = sizeY, sizeX 2247 2248 if self._useAero: 2249 self.CreateShapesWithStyle(useWhidbey) 2250 2251 if wx.Platform == "__WXGTK__": 2252 self.Bind(wx.EVT_WINDOW_CREATE, self.SetGuideShape) 2253 else: 2254 self.SetGuideShape() 2255 2256 self.SetSize(self.region.GetBox().GetSize()) 2257 else: 2258 self.SetSize((sizeX, sizeY)) 2259 2260 self.rect = wx.Rect(0, 0, sizeX, sizeY) 2261 2262 if self._useAero: 2263 useAero = (useWhidbey and [2] or [1])[0] 2264 else: 2265 useAero = 0 2266 2267 self.target = AuiDockingGuideWindow(self, self.rect, direction, False, useAero)
2268 2269
2270 - def CreateShapesWithStyle(self, useWhidbey):
2271 """ 2272 Creates the docking guide window shape based on which docking bitmaps are used. 2273 2274 :param bool `useWhidbey`: if ``True``, use Whidbey-style bitmaps; if ``False``, use the 2275 Aero-style bitmaps. 2276 """ 2277 2278 sizeX, sizeY = aeroguideSizeX, aeroguideSizeY 2279 if useWhidbey: 2280 sizeX, sizeY = whidbeySizeX, whidbeySizeY 2281 2282 if self._direction not in [wx.TOP, wx.BOTTOM]: 2283 sizeX, sizeY = sizeY, sizeX 2284 2285 useAero = (useWhidbey and [2] or [1])[0] 2286 bmp, dummy = GetDockingImage(self._direction, useAero, False) 2287 region = wx.RegionFromBitmap(bmp) 2288 2289 self.region = region
2290 2291
2292 - def AeroMove(self, pos):
2293 """ 2294 Moves the docking window to the new position. Overridden in children classes. 2295 2296 :param Point `pos`: the new docking guide position. 2297 """ 2298 2299 pass
2300 2301
2302 - def SetGuideShape(self, event=None):
2303 """ 2304 Sets the correct shape for the docking guide window. 2305 2306 :param `event`: on wxGTK, a :class:`WindowCreateEvent` event to process. 2307 """ 2308 2309 self.SetShape(self.region) 2310 2311 if event is not None: 2312 # Skip the event on wxGTK 2313 event.Skip() 2314 wx.CallAfter(wx.SafeYield, self, True)
2315 2316
2317 - def SetShape(self, region):
2318 """ 2319 If the platform supports it, sets the shape of the window to that depicted by `region`. 2320 The system will not display or respond to any mouse event for the pixels that lie 2321 outside of the region. To reset the window to the normal rectangular shape simply call 2322 :meth:`SetShape` again with an empty region. 2323 2324 :param Region `region`: the shape of the frame. 2325 2326 :note: Overridden for wxMAC. 2327 """ 2328 2329 if wx.Platform == '__WXMAC__': 2330 # HACK so we don't crash when SetShape is called 2331 return 2332 else: 2333 super(AuiSingleDockingGuide, self).SetShape(region)
2334 2335
2336 - def SetValid(self, valid):
2337 """ 2338 Sets the docking direction as valid or invalid. 2339 2340 :param bool `valid`: whether the docking direction is allowed or not. 2341 """ 2342 2343 self._valid = valid
2344 2345
2346 - def IsValid(self):
2347 """ Returns whether the docking direction is valid. """ 2348 2349 return self._valid
2350 2351
2352 - def UpdateDockGuide(self, pos):
2353 """ 2354 Updates the docking guide images depending on the mouse position, using focused 2355 images if the mouse is inside the docking guide or unfocused images if it is 2356 outside. 2357 2358 :param Point `pos`: the mouse position. 2359 """ 2360 2361 self.target.UpdateDockGuide(pos)
2362 2363
2364 - def HitTest(self, x, y):
2365 """ 2366 Checks if the mouse position is inside the target window rect. 2367 2368 :param integer `x`: the `x` mouse position; 2369 :param integer `y`: the `y` mouse position. 2370 """ 2371 2372 if self.target.GetScreenRect().Contains((x, y)): 2373 return wx.ALL 2374 2375 return -1
2376 2377 2378 # --------------------------------------------------------------------------- 2379 # AuiCenterDockingGuide 2380 # --------------------------------------------------------------------------- 2381
2382 -class AuiCenterDockingGuide(AuiDockingGuide):
2383 """ A docking guide window for multiple docking hint (diamond-shaped HUD). """ 2384
2385 - def __init__(self, parent):
2386 """ 2387 Default class constructor. 2388 Used internally, do not call it in your code! 2389 2390 :param `parent`: the :class:`AuiManager` parent. 2391 """ 2392 2393 AuiDockingGuide.__init__(self, parent, style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP | 2394 wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.FRAME_SHAPED, 2395 name="auiCenterDockTarget") 2396 2397 self.Hide() 2398 2399 self.CreateShapesWithStyle() 2400 self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) 2401 2402 if wx.Platform == "__WXGTK__": 2403 self.Bind(wx.EVT_WINDOW_CREATE, self.SetGuideShape) 2404 else: 2405 self.SetGuideShape() 2406 2407 self.SetSize(self.region.GetBox().GetSize()) 2408 2409 self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) 2410 self.Bind(wx.EVT_PAINT, self.OnPaint)
2411 2412
2413 - def CreateShapesWithStyle(self):
2414 """ Creates the docking guide window shape based on which docking bitmaps are used. """ 2415 2416 useAero = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_AERO_DOCKING_GUIDES) != 0 2417 useWhidbey = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES) != 0 2418 2419 self._useAero = 0 2420 if useAero: 2421 self._useAero = 1 2422 elif useWhidbey: 2423 self._useAero = 2 2424 2425 if useAero: 2426 sizeX, sizeY = aeroguideSizeX, aeroguideSizeY 2427 elif useWhidbey: 2428 sizeX, sizeY = whidbeySizeX, whidbeySizeY 2429 else: 2430 sizeX, sizeY = guideSizeX, guideSizeY 2431 2432 rectLeft = wx.Rect(0, sizeY, sizeY, sizeX) 2433 rectTop = wx.Rect(sizeY, 0, sizeX, sizeY) 2434 rectRight = wx.Rect(sizeY+sizeX, sizeY, sizeY, sizeX) 2435 rectBottom = wx.Rect(sizeY, sizeX + sizeY, sizeX, sizeY) 2436 rectCenter = wx.Rect(sizeY, sizeY, sizeX, sizeX) 2437 2438 if not self._useAero: 2439 2440 self.targetLeft = AuiDockingGuideWindow(self, rectLeft, wx.LEFT, True, useAero) 2441 self.targetTop = AuiDockingGuideWindow(self, rectTop, wx.TOP, True, useAero) 2442 self.targetRight = AuiDockingGuideWindow(self, rectRight, wx.RIGHT, True, useAero) 2443 self.targetBottom = AuiDockingGuideWindow(self, rectBottom, wx.BOTTOM, True, useAero) 2444 self.targetCenter = AuiDockingGuideWindow(self, rectCenter, wx.CENTER, True, useAero) 2445 2446 2447 # top-left diamond 2448 tld = [wx.Point(rectTop.x, rectTop.y+rectTop.height-8), 2449 wx.Point(rectLeft.x+rectLeft.width-8, rectLeft.y), 2450 rectTop.GetBottomLeft()] 2451 # bottom-left diamond 2452 bld = [wx.Point(rectLeft.x+rectLeft.width-8, rectLeft.y+rectLeft.height), 2453 wx.Point(rectBottom.x, rectBottom.y+8), 2454 rectBottom.GetTopLeft()] 2455 # top-right diamond 2456 trd = [wx.Point(rectTop.x+rectTop.width, rectTop.y+rectTop.height-8), 2457 wx.Point(rectRight.x+8, rectRight.y), 2458 rectRight.GetTopLeft()] 2459 # bottom-right diamond 2460 brd = [wx.Point(rectRight.x+8, rectRight.y+rectRight.height), 2461 wx.Point(rectBottom.x+rectBottom.width, rectBottom.y+8), 2462 rectBottom.GetTopRight()] 2463 2464 self._triangles = [tld[0:2], bld[0:2], 2465 [wx.Point(rectTop.x+rectTop.width-1, rectTop.y+rectTop.height-8), 2466 wx.Point(rectRight.x+7, rectRight.y)], 2467 [wx.Point(rectRight.x+7, rectRight.y+rectRight.height), 2468 wx.Point(rectBottom.x+rectBottom.width-1, rectBottom.y+8)]] 2469 2470 region = wx.Region() 2471 region.UnionRect(rectLeft) 2472 region.UnionRect(rectTop) 2473 region.UnionRect(rectRight) 2474 region.UnionRect(rectBottom) 2475 region.UnionRect(rectCenter) 2476 region.UnionRegion(wx.RegionFromPoints(tld)) 2477 region.UnionRegion(wx.RegionFromPoints(bld)) 2478 region.UnionRegion(wx.RegionFromPoints(trd)) 2479 region.UnionRegion(wx.RegionFromPoints(brd)) 2480 2481 elif useAero: 2482 2483 self._aeroBmp = aero_dock_pane.GetBitmap() 2484 region = wx.RegionFromBitmap(self._aeroBmp) 2485 2486 self._allAeroBmps = [aero_dock_pane_left.GetBitmap(), aero_dock_pane_top.GetBitmap(), 2487 aero_dock_pane_right.GetBitmap(), aero_dock_pane_bottom.GetBitmap(), 2488 aero_dock_pane_center.GetBitmap(), aero_dock_pane.GetBitmap()] 2489 self._deniedBitmap = aero_denied.GetBitmap() 2490 self._aeroRects = [rectLeft, rectTop, rectRight, rectBottom, rectCenter] 2491 self._valid = True 2492 2493 elif useWhidbey: 2494 2495 self._aeroBmp = whidbey_dock_pane.GetBitmap() 2496 region = wx.RegionFromBitmap(self._aeroBmp) 2497 2498 self._allAeroBmps = [whidbey_dock_pane_left.GetBitmap(), whidbey_dock_pane_top.GetBitmap(), 2499 whidbey_dock_pane_right.GetBitmap(), whidbey_dock_pane_bottom.GetBitmap(), 2500 whidbey_dock_pane_center.GetBitmap(), whidbey_dock_pane.GetBitmap()] 2501 self._deniedBitmap = whidbey_denied.GetBitmap() 2502 self._aeroRects = [rectLeft, rectTop, rectRight, rectBottom, rectCenter] 2503 self._valid = True 2504 2505 2506 self.region = region
2507 2508
2509 - def SetGuideShape(self, event=None):
2510 """ 2511 Sets the correct shape for the docking guide window. 2512 2513 :param `event`: on wxGTK, a :class:`WindowCreateEvent` event to process. 2514 """ 2515 2516 self.SetShape(self.region) 2517 2518 if event is not None: 2519 # Skip the event on wxGTK 2520 event.Skip() 2521 wx.CallAfter(wx.SafeYield, self, True)
2522 2523
2524 - def UpdateDockGuide(self, pos):
2525 """ 2526 Updates the docking guides images depending on the mouse position, using focused 2527 images if the mouse is inside the docking guide or unfocused images if it is 2528 outside. 2529 2530 :param Point `pos`: the mouse position. 2531 """ 2532 2533 if not self._useAero: 2534 for target in self.GetChildren(): 2535 target.UpdateDockGuide(pos) 2536 else: 2537 lenRects = len(self._aeroRects) 2538 for indx, rect in enumerate(self._aeroRects): 2539 if rect.Contains(pos): 2540 if self._allAeroBmps[indx] != self._aeroBmp: 2541 if indx < lenRects - 1 or (indx == lenRects - 1 and self._valid): 2542 self._aeroBmp = self._allAeroBmps[indx] 2543 self.Refresh() 2544 else: 2545 self._aeroBmp = self._allAeroBmps[-1] 2546 self.Refresh() 2547 2548 return 2549 2550 if self._aeroBmp != self._allAeroBmps[-1]: 2551 self._aeroBmp = self._allAeroBmps[-1] 2552 self.Refresh()
2553 2554
2555 - def HitTest(self, x, y):
2556 """ 2557 Checks if the mouse position is inside the target windows rect. 2558 2559 :param integer `x`: the `x` mouse position; 2560 :param integer `y`: the `y` mouse position. 2561 """ 2562 2563 if not self._useAero: 2564 if self.targetLeft.GetScreenRect().Contains((x, y)): 2565 return wx.LEFT 2566 if self.targetTop.GetScreenRect().Contains((x, y)): 2567 return wx.UP 2568 if self.targetRight.GetScreenRect().Contains((x, y)): 2569 return wx.RIGHT 2570 if self.targetBottom.GetScreenRect().Contains((x, y)): 2571 return wx.DOWN 2572 if self.targetCenter.IsValid() and self.targetCenter.GetScreenRect().Contains((x, y)): 2573 return wx.CENTER 2574 else: 2575 constants = [wx.LEFT, wx.UP, wx.RIGHT, wx.DOWN, wx.CENTER] 2576 lenRects = len(self._aeroRects) 2577 for indx, rect in enumerate(self._aeroRects): 2578 if rect.Contains((x, y)): 2579 if indx < lenRects or (indx == lenRects-1 and self._valid): 2580 return constants[indx] 2581 2582 return -1
2583 2584
2585 - def ValidateNotebookDocking(self, valid):
2586 """ 2587 Sets whether a pane can be docked on top of another to create an automatic 2588 :class:`~lib.agw.aui.auibook.AuiNotebook`. 2589 2590 :param bool `valid`: whether a pane can be docked on top to another to form an automatic 2591 :class:`~lib.agw.aui.auibook.AuiNotebook`. 2592 """ 2593 2594 if not self._useAero: 2595 if self.targetCenter.IsValid() != valid: 2596 self.targetCenter.SetValid(valid) 2597 self.targetCenter.Refresh() 2598 else: 2599 if self._valid != valid: 2600 self._valid = valid 2601 self.Refresh()
2602 2603
2604 - def AeroMove(self, pos):
2605 """ 2606 Moves the docking guide window to the new position. 2607 2608 :param Point `pos`: the new docking guide position. 2609 """ 2610 2611 if not self._useAero: 2612 return 2613 2614 useWhidbey = (GetManager(self.GetParent()).GetAGWFlags() & AUI_MGR_WHIDBEY_DOCKING_GUIDES) != 0 2615 2616 if useWhidbey: 2617 sizeX, sizeY = whidbeySizeX, whidbeySizeY 2618 else: 2619 sizeX, sizeY = aeroguideSizeX, aeroguideSizeY 2620 2621 size = self.GetSize() 2622 2623 leftRect, topRect, rightRect, bottomRect, centerRect = self._aeroRects 2624 thePos = pos + wx.Point((size.x-sizeY)/2, (size.y-sizeX)/2) 2625 2626 centerRect.SetPosition(thePos) 2627 2628 leftRect.SetPosition(thePos + wx.Point(-sizeY, 0)) 2629 topRect.SetPosition(thePos + wx.Point(0, -sizeY)) 2630 rightRect.SetPosition(thePos + wx.Point(sizeX, 0)) 2631 bottomRect.SetPosition(thePos + wx.Point(0, sizeX))
2632 2633
2634 - def OnEraseBackground(self, event):
2635 """ 2636 Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiCenterDockingGuide`. 2637 2638 :param `event`: :class:`EraseEvent` to be processed. 2639 2640 :note: This is intentionally empty to reduce flickering while drawing. 2641 """ 2642 2643 pass
2644 2645
2646 - def OnPaint(self, event):
2647 """ 2648 Handles the ``wx.EVT_PAINT`` event for :class:`AuiCenterDockingGuide`. 2649 2650 :param `event`: a :class:`PaintEvent` to be processed. 2651 """ 2652 2653 dc = wx.AutoBufferedPaintDC(self) 2654 2655 if self._useAero: 2656 dc.SetBrush(wx.TRANSPARENT_BRUSH) 2657 dc.SetPen(wx.TRANSPARENT_PEN) 2658 else: 2659 dc.SetBrush(wx.Brush(colourTargetBackground)) 2660 dc.SetPen(wx.Pen(colourTargetBorder)) 2661 2662 rect = self.GetClientRect() 2663 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) 2664 2665 if self._useAero: 2666 dc.DrawBitmap(self._aeroBmp, 0, 0, True) 2667 if not self._valid: 2668 diff = (self._useAero == 2 and [1] or [0])[0] 2669 bmpX, bmpY = self._deniedBitmap.GetWidth(), self._deniedBitmap.GetHeight() 2670 xPos, yPos = (rect.x + (rect.width)/2 - bmpX/2), (rect.y + (rect.height)/2 - bmpY/2) 2671 dc.DrawBitmap(self._deniedBitmap, xPos+1, yPos+diff, True) 2672 2673 return 2674 2675 dc.SetPen(wx.Pen(colourTargetBorder, 2)) 2676 for pts in self._triangles: 2677 dc.DrawLinePoint(pts[0], pts[1])
2678 2679 2680 # ---------------------------------------------------------------------------- 2681 # AuiDockingHintWindow 2682 # ---------------------------------------------------------------------------- 2683
2684 -class AuiDockingHintWindow(wx.Frame):
2685 """ The original wxAUI docking window hint. """ 2686
2687 - def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition, 2688 size=wx.Size(1, 1), style=wx.FRAME_TOOL_WINDOW | wx.FRAME_FLOAT_ON_PARENT | 2689 wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.FRAME_SHAPED, 2690 name="auiHintWindow"):
2691 """ 2692 Default class constructor. Used internally, do not call it in your code! 2693 2694 :param `parent`: the :class:`AuiManager` parent; 2695 :param integer `id`: the window identifier. It may take a value of -1 to indicate a default value. 2696 :param string `title`: the caption to be displayed on the frame's title bar; 2697 :param Point `pos`: the window position. A value of (-1, -1) indicates a default position, 2698 chosen by either the windowing system or wxPython, depending on platform; 2699 :param Size `size`: the window size. A value of (-1, -1) indicates a default size, chosen by 2700 either the windowing system or wxPython, depending on platform; 2701 :param integer `style`: the window style; 2702 :param string `name`: the name of the window. This parameter is used to associate a name with the 2703 item, allowing the application user to set Motif resource values for individual windows. 2704 """ 2705 if wx.Platform == '__WXMAC__' and style & wx.FRAME_SHAPED: 2706 # Having the shaped frame causes the frame to not be visible 2707 # with the transparent style hints. 2708 style -= wx.FRAME_SHAPED 2709 2710 wx.Frame.__init__(self, parent, id, title, pos, size, style, name=name) 2711 2712 self._blindMode = False 2713 2714 self._art = parent.GetEventHandler().GetArtProvider() 2715 background = self._art.GetColour(AUI_DOCKART_HINT_WINDOW_COLOUR) 2716 self.SetBackgroundColour(background) 2717 2718 # Can't set background colour on a frame on wxMac 2719 # so add a panel to set the colour on. 2720 if wx.Platform == '__WXMAC__': 2721 sizer = wx.BoxSizer(wx.HORIZONTAL) 2722 self.panel = wx.Panel(self) 2723 sizer.Add(self.panel, 1, wx.EXPAND) 2724 self.SetSizer(sizer) 2725 self.panel.SetBackgroundColour(background) 2726 else: 2727 self.Bind(wx.EVT_PAINT, self.OnPaint) 2728 2729 self.Bind(wx.EVT_SIZE, self.OnSize)
2730 2731
2732 - def MakeVenetianBlinds(self):
2733 """ 2734 Creates the "venetian blind" effect if :class:`AuiManager` has the ``AUI_MGR_VENETIAN_BLINDS_HINT`` 2735 flag set. 2736 """ 2737 2738 amount = 128 2739 size = self.GetClientSize() 2740 region = wx.Region(0, 0, size.x, 1) 2741 2742 for y in xrange(size.y): 2743 2744 # Reverse the order of the bottom 4 bits 2745 j = (y & 8 and [1] or [0])[0] | (y & 4 and [2] or [0])[0] | \ 2746 (y & 2 and [4] or [0])[0] | (y & 1 and [8] or [0])[0] 2747 2748 if 16*j+8 < amount: 2749 region.Union(0, y, size.x, 1) 2750 2751 self.SetShape(region)
2752 2753
2754 - def SetBlindMode(self, agwFlags):
2755 """ 2756 Sets whether venetian blinds or transparent hints will be shown as docking hint. 2757 This depends on the :class:`AuiManager` flags. 2758 2759 :param integer `agwFlags`: the :class:`AuiManager` flags. 2760 """ 2761 2762 self._blindMode = (agwFlags & AUI_MGR_VENETIAN_BLINDS_HINT) != 0 2763 2764 if self._blindMode or not self.CanSetTransparent(): 2765 self.MakeVenetianBlinds() 2766 self.SetTransparent(255) 2767 2768 else: 2769 self.SetShape(wx.Region()) 2770 if agwFlags & AUI_MGR_HINT_FADE == 0: 2771 self.SetTransparent(80) 2772 else: 2773 self.SetTransparent(0)
2774 2775
2776 - def SetShape(self, region):
2777 """ 2778 If the platform supports it, sets the shape of the window to that depicted by `region`. 2779 The system will not display or respond to any mouse event for the pixels that lie 2780 outside of the region. To reset the window to the normal rectangular shape simply call 2781 :meth:`SetShape` again with an empty region. 2782 2783 :param Region `region`: the shape of the frame. 2784 2785 :note: Overridden for wxMAC. 2786 """ 2787 2788 if wx.Platform == '__WXMAC__': 2789 # HACK so we don't crash when SetShape is called 2790 return 2791 else: 2792 super(AuiDockingHintWindow, self).SetShape(region)
2793 2794
2795 - def Show(self, show=True):
2796 """ 2797 Show the hint window. 2798 2799 :param bool `show`: whether to show or hide the hint docking window. 2800 """ 2801 2802 background = self._art.GetColour(AUI_DOCKART_HINT_WINDOW_COLOUR) 2803 2804 if wx.Platform == '__WXMAC__': 2805 self.panel.SetBackgroundColour(background) 2806 else: 2807 self.SetBackgroundColour(background) 2808 2809 super(AuiDockingHintWindow, self).Show(show) 2810 self.Refresh() 2811 2812 if wx.Platform == '__WXMAC__': 2813 # Need to manually do layout since its a borderless frame. 2814 self.Layout()
2815 2816
2817 - def OnSize(self, event):
2818 """ 2819 Handles the ``wx.EVT_SIZE`` event for :class:`AuiDockingHintWindow`. 2820 2821 :param `event`: a :class:`SizeEvent` to be processed. 2822 """ 2823 2824 if self._blindMode or not self.CanSetTransparent(): 2825 self.MakeVenetianBlinds() 2826 2827 self.Refresh()
2828 2829
2830 - def OnPaint(self, event):
2831 """ 2832 Handles the ``wx.EVT_PAINT`` event for :class:`AuiDockingHintWindow`. 2833 2834 :param `event`: an instance of :class:`PaintEvent` to be processed. 2835 """ 2836 2837 rect = wx.RectPS(wx.Point(0, 0), self.GetSize()) 2838 2839 dc = wx.PaintDC(self) 2840 event.Skip() 2841 2842 dc.SetBrush(wx.TRANSPARENT_BRUSH) 2843 dc.SetPen(wx.Pen(wx.Colour(60, 60, 60), 5)) 2844 rect.Deflate(1, 1) 2845 dc.DrawRectangleRect(rect)
2846 2847 2848 # ---------------------------------------------------------------------------- # 2849 2850 # -- AuiFloatingFrame class implementation -- 2851
2852 -class AuiFloatingFrame(wx.MiniFrame):
2853 """ AuiFloatingFrame is the frame class that holds floating panes. """ 2854
2855 - def __init__(self, parent, owner_mgr, pane=None, id=wx.ID_ANY, title="", 2856 style=wx.FRAME_TOOL_WINDOW | wx.FRAME_FLOAT_ON_PARENT | 2857 wx.FRAME_NO_TASKBAR | wx.CLIP_CHILDREN):
2858 """ 2859 Default class constructor. Used internally, do not call it in your code! 2860 2861 :param `parent`: the :class:`AuiManager` parent; 2862 :param `owner_mgr`: the :class:`AuiManager` that manages the floating pane; 2863 :param `pane`: the :class:`AuiPaneInfo` pane that is about to float; 2864 :param integer `id`: the window identifier. It may take a value of -1 to indicate a default value. 2865 :param string `title`: the caption to be displayed on the frame's title bar. 2866 :param integer `style`: the window style. 2867 """ 2868 2869 if pane and pane.IsResizeable(): 2870 style += wx.RESIZE_BORDER 2871 if pane: 2872 self._is_toolbar = pane.IsToolbar() 2873 2874 self._useNativeMiniframes = False 2875 if AuiManager_UseNativeMiniframes(owner_mgr): 2876 # On wxMac we always use native miniframes 2877 self._useNativeMiniframes = True 2878 style += wx.CAPTION + wx.SYSTEM_MENU 2879 if pane.HasCloseButton(): 2880 style += wx.CLOSE_BOX 2881 if pane.HasMaximizeButton(): 2882 style += wx.MAXIMIZE_BOX 2883 if pane.HasMinimizeButton(): 2884 style += wx.MINIMIZE_BOX 2885 2886 wx.MiniFrame.__init__(self, parent, id, title, pos=pane.floating_pos, 2887 size=pane.floating_size, style=style, name="auiFloatingFrame") 2888 2889 self._fly_timer = wx.Timer(self, wx.ID_ANY) 2890 self._check_fly_timer = wx.Timer(self, wx.ID_ANY) 2891 2892 self.Bind(wx.EVT_CLOSE, self.OnClose) 2893 self.Bind(wx.EVT_SIZE, self.OnSize) 2894 self.Bind(wx.EVT_ACTIVATE, self.OnActivate) 2895 self.Bind(wx.EVT_TIMER, self.OnCheckFlyTimer, self._check_fly_timer) 2896 self.Bind(wx.EVT_TIMER, self.OnFlyTimer, self._fly_timer) 2897 self.Bind(EVT_AUI_FIND_MANAGER, self.OnFindManager) 2898 2899 if self._useNativeMiniframes: 2900 self.Bind(wx.EVT_MOVE, self.OnMoveEvent) 2901 self.Bind(wx.EVT_MOVING, self.OnMoveEvent) 2902 self.Bind(wx.EVT_IDLE, self.OnIdle) 2903 self._useNativeMiniframes = True 2904 self.SetExtraStyle(wx.WS_EX_PROCESS_IDLE) 2905 else: 2906 self.Bind(wx.EVT_MOVE, self.OnMove) 2907 2908 self._fly = False 2909 self._send_size = True 2910 self._alpha_amount = 255 2911 2912 self._owner_mgr = owner_mgr 2913 self._moving = False 2914 self._lastDirection = None 2915 self._transparent = 255 2916 2917 self._last_rect = wx.Rect() 2918 self._last2_rect = wx.Rect() 2919 self._last3_rect = wx.Rect() 2920 2921 self._mgr = AuiManager() 2922 self._mgr.SetManagedWindow(self) 2923 self._mgr.SetArtProvider(owner_mgr.GetArtProvider()) 2924 self._mgr.SetAGWFlags(owner_mgr.GetAGWFlags())
2925 2926
2927 - def CopyAttributes(self, pane):
2928 """ 2929 Copies all the attributes of the input `pane` into another :class:`AuiPaneInfo`. 2930 2931 :param `pane`: the source :class:`AuiPaneInfo` from where to copy attributes. 2932 """ 2933 2934 contained_pane = AuiPaneInfo() 2935 2936 contained_pane.name = pane.name 2937 contained_pane.caption = pane.caption 2938 contained_pane.window = pane.window 2939 contained_pane.frame = pane.frame 2940 contained_pane.state = pane.state 2941 contained_pane.dock_direction = pane.dock_direction 2942 contained_pane.dock_layer = pane.dock_layer 2943 contained_pane.dock_row = pane.dock_row 2944 contained_pane.dock_pos = pane.dock_pos 2945 contained_pane.best_size = wx.Size(*pane.best_size) 2946 contained_pane.min_size = wx.Size(*pane.min_size) 2947 contained_pane.max_size = wx.Size(*pane.max_size) 2948 contained_pane.floating_pos = wx.Point(*pane.floating_pos) 2949 contained_pane.floating_size = wx.Size(*pane.floating_size) 2950 contained_pane.dock_proportion = pane.dock_proportion 2951 contained_pane.buttons = pane.buttons 2952 contained_pane.rect = wx.Rect(*pane.rect) 2953 contained_pane.icon = pane.icon 2954 contained_pane.notebook_id = pane.notebook_id 2955 contained_pane.transparent = pane.transparent 2956 contained_pane.snapped = pane.snapped 2957 contained_pane.minimize_mode = pane.minimize_mode 2958 contained_pane.minimize_target = pane.minimize_target 2959 2960 return contained_pane
2961 2962
2963 - def SetPaneWindow(self, pane):
2964 """ 2965 Sets all the properties of a pane. 2966 2967 :param `pane`: the :class:`AuiPaneInfo` to analyze. 2968 """ 2969 2970 self._is_toolbar = pane.IsToolbar() 2971 self._pane_window = pane.window 2972 2973 if isinstance(pane.window, auibar.AuiToolBar): 2974 pane.window.SetAuiManager(self._mgr) 2975 2976 self._pane_window.Reparent(self) 2977 2978 contained_pane = self.CopyAttributes(pane) 2979 2980 contained_pane.Dock().Center().Show(). \ 2981 CaptionVisible(False). \ 2982 PaneBorder(False). \ 2983 Layer(0).Row(0).Position(0) 2984 2985 if not contained_pane.HasGripper() and not self._useNativeMiniframes: 2986 contained_pane.CaptionVisible(True) 2987 2988 indx = self._owner_mgr._panes.index(pane) 2989 2990 # Carry over the minimum size 2991 pane_min_size = pane.window.GetMinSize() 2992 2993 # if the best size is smaller than the min size 2994 # then set the min size to the best size as well 2995 pane_best_size = contained_pane.best_size 2996 if pane_best_size.IsFullySpecified() and (pane_best_size.x < pane_min_size.x or \ 2997 pane_best_size.y < pane_min_size.y): 2998 2999 pane_min_size = pane_best_size 3000 self._pane_window.SetMinSize(pane_min_size) 3001 3002 # if the frame window's max size is greater than the min size 3003 # then set the max size to the min size as well 3004 cur_max_size = self.GetMaxSize() 3005 if cur_max_size.IsFullySpecified() and (cur_max_size.x < pane_min_size.x or \ 3006 cur_max_size.y < pane_min_size.y): 3007 self.SetMaxSize(pane_min_size) 3008 3009 art_provider = self._mgr.GetArtProvider() 3010 caption_size = art_provider.GetMetric(AUI_DOCKART_CAPTION_SIZE) 3011 button_size = art_provider.GetMetric(AUI_DOCKART_PANE_BUTTON_SIZE) + \ 3012 4*art_provider.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) 3013 3014 min_size = pane.window.GetMinSize() 3015 3016 if min_size.y < caption_size or min_size.x < button_size: 3017 new_x, new_y = min_size.x, min_size.y 3018 if min_size.y < caption_size: 3019 new_y = (pane.IsResizeable() and [2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y)+caption_size] or [1])[0] 3020 if min_size.x < button_size: 3021 new_x = (pane.IsResizeable() and [2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_X)+button_size] or [1])[0] 3022 3023 self.SetMinSize((new_x, new_y)) 3024 else: 3025 self.SetMinSize(min_size) 3026 3027 self._mgr.AddPane(self._pane_window, contained_pane) 3028 self._mgr.Update() 3029 3030 if pane.min_size.IsFullySpecified(): 3031 # because SetSizeHints() calls Fit() too (which sets the window 3032 # size to its minimum allowed), we keep the size before calling 3033 # SetSizeHints() and reset it afterwards... 3034 tmp = self.GetSize() 3035 self.GetSizer().SetSizeHints(self) 3036 self.SetSize(tmp) 3037 3038 self.SetTitle(pane.caption) 3039 3040 if pane.floating_size != wx.Size(-1, -1): 3041 self.SetSize(pane.floating_size) 3042 else: 3043 size = pane.best_size 3044 if size == wx.Size(-1, -1): 3045 size = pane.min_size 3046 if size == wx.Size(-1, -1): 3047 size = self._pane_window.GetSize() 3048 if self._owner_mgr and pane.HasGripper(): 3049 if pane.HasGripperTop(): 3050 size.y += self._owner_mgr._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE) 3051 else: 3052 size.x += self._owner_mgr._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE) 3053 3054 if not self._useNativeMiniframes: 3055 size.y += self._owner_mgr._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) 3056 3057 pane.floating_size = size 3058 3059 self.SetClientSize(size) 3060 3061 self._owner_mgr._panes[indx] = pane 3062 3063 self._fly_step = abs(pane.floating_size.y - \ 3064 (caption_size + 2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y)))/10 3065 3066 self._floating_size = wx.Size(*self.GetSize()) 3067 3068 if pane.IsFlyOut(): 3069 self._check_fly_timer.Start(50)
3070 3071
3072 - def GetOwnerManager(self):
3073 """ Returns the :class:`AuiManager` that manages the pane. """ 3074 3075 return self._owner_mgr
3076 3077
3078 - def OnSize(self, event):
3079 """ 3080 Handles the ``wx.EVT_SIZE`` event for :class:`AuiFloatingFrame`. 3081 3082 :param `event`: a :class:`SizeEvent` to be processed. 3083 """ 3084 3085 if self._owner_mgr and self._send_size: 3086 self._owner_mgr.OnFloatingPaneResized(self._pane_window, event.GetSize())
3087 3088
3089 - def OnClose(self, event):
3090 """ 3091 Handles the ``wx.EVT_CLOSE`` event for :class:`AuiFloatingFrame`. 3092 3093 :param `event`: a :class:`CloseEvent` to be processed. 3094 """ 3095 3096 if self._owner_mgr: 3097 self._owner_mgr.OnFloatingPaneClosed(self._pane_window, event) 3098 3099 if not event.GetVeto(): 3100 self._mgr.DetachPane(self._pane_window) 3101 3102 if isinstance(self._pane_window, auibar.AuiToolBar): 3103 self._pane_window.SetAuiManager(self._owner_mgr) 3104 3105 # if we do not do this, then we can crash... 3106 if self._owner_mgr and self._owner_mgr._action_window == self: 3107 self._owner_mgr._action_window = None 3108 3109 self._mgr.UnInit() 3110 self.Destroy()
3111 3112
3113 - def OnActivate(self, event):
3114 """ 3115 Handles the ``wx.EVT_ACTIVATE`` event for :class:`AuiFloatingFrame`. 3116 3117 :param `event`: a :class:`ActivateEvent` to be processed. 3118 """ 3119 3120 if self._owner_mgr and event.GetActive(): 3121 self._owner_mgr.OnFloatingPaneActivated(self._pane_window)
3122 3123
3124 - def OnMove(self, event):
3125 """ 3126 Handles the ``wx.EVT_MOVE`` event for :class:`AuiFloatingFrame`. 3127 3128 :param `event`: a :class:`MoveEvent` to be processed. 3129 3130 .. note:: 3131 3132 This event is not processed on wxMAC or if :class:`AuiManager` is not using the 3133 ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. 3134 3135 """ 3136 3137 if self._owner_mgr: 3138 self._owner_mgr.OnFloatingPaneMoved(self._pane_window, event)
3139 3140
3141 - def OnMoveEvent(self, event):
3142 """ 3143 Handles the ``wx.EVT_MOVE`` and ``wx.EVT_MOVING`` events for :class:`AuiFloatingFrame`. 3144 3145 :param `event`: a :class:`MoveEvent` to be processed. 3146 3147 .. note:: 3148 3149 This event is only processed on wxMAC or if :class:`AuiManager` is using the 3150 ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. 3151 """ 3152 3153 win_rect = self.GetRect() 3154 3155 if win_rect == self._last_rect: 3156 return 3157 3158 # skip the first move event 3159 if self._last_rect.IsEmpty(): 3160 self._last_rect = wx.Rect(*win_rect) 3161 return 3162 3163 # As on OSX moving windows are not getting all move events, only sporadically, this difference 3164 # is almost always big on OSX, so avoid this early exit opportunity 3165 if wx.Platform != '__WXMAC__': 3166 # skip if moving too fast to avoid massive redraws and 3167 # jumping hint windows 3168 if abs(win_rect.x - self._last_rect.x) > 3 or abs(win_rect.y - self._last_rect.y) > 3: 3169 self._last3_rect = wx.Rect(*self._last2_rect) 3170 self._last2_rect = wx.Rect(*self._last_rect) 3171 self._last_rect = wx.Rect(*win_rect) 3172 3173 # However still update the internally stored position to avoid 3174 # snapping back to the old one later. 3175 if self._owner_mgr: 3176 self._owner_mgr.GetPane(self._pane_window).floating_pos = win_rect.GetPosition() 3177 3178 return 3179 3180 # prevent frame redocking during resize 3181 if self._last_rect.GetSize() != win_rect.GetSize(): 3182 self._last3_rect = wx.Rect(*self._last2_rect) 3183 self._last2_rect = wx.Rect(*self._last_rect) 3184 self._last_rect = wx.Rect(*win_rect) 3185 return 3186 3187 dir = wx.ALL 3188 3189 horiz_dist = abs(win_rect.x - self._last3_rect.x) 3190 vert_dist = abs(win_rect.y - self._last3_rect.y) 3191 3192 if vert_dist >= horiz_dist: 3193 if win_rect.y < self._last3_rect.y: 3194 dir = wx.NORTH 3195 else: 3196 dir = wx.SOUTH 3197 else: 3198 if win_rect.x < self._last3_rect.x: 3199 dir = wx.WEST 3200 else: 3201 dir = wx.EAST 3202 3203 self._last3_rect = wx.Rect(*self._last2_rect) 3204 self._last2_rect = wx.Rect(*self._last_rect) 3205 self._last_rect = wx.Rect(*win_rect) 3206 3207 if _VERSION_STRING < "2.9": 3208 leftDown = wx.GetMouseState().LeftDown() 3209 else: 3210 leftDown = wx.GetMouseState().LeftIsDown() 3211 3212 if not leftDown: 3213 return 3214 3215 if not self._moving: 3216 self.OnMoveStart(event) 3217 self._moving = True 3218 3219 if self._last3_rect.IsEmpty(): 3220 return 3221 3222 if event.GetEventType() == wx.wxEVT_MOVING: 3223 self.OnMoving(event.GetRect(), dir) 3224 else: 3225 self.OnMoving(wx.RectPS(event.GetPosition(), self.GetSize()), dir)
3226 3227
3228 - def OnIdle(self, event):
3229 """ 3230 Handles the ``wx.EVT_IDLE`` event for :class:`AuiFloatingFrame`. 3231 3232 :param `event`: a :class:`IdleEvent` event to be processed. 3233 3234 .. note:: 3235 3236 This event is only processed on wxMAC if :class:`AuiManager` is using the 3237 ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. 3238 3239 """ 3240 3241 if self._moving: 3242 if _VERSION_STRING < "2.9": 3243 leftDown = wx.GetMouseState().LeftDown() 3244 else: 3245 leftDown = wx.GetMouseState().LeftIsDown() 3246 3247 if not leftDown: 3248 self._moving = False 3249 self.OnMoveFinished() 3250 else: 3251 event.RequestMore()
3252 3253
3254 - def OnMoveStart(self, event):
3255 """ 3256 The user has just started moving the floating pane. 3257 3258 :param `event`: an instance of :class:`MouseEvent`. 3259 3260 .. note:: 3261 3262 This event is only processed on wxMAC if :class:`AuiManager` is using the 3263 ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. 3264 3265 """ 3266 3267 # notify the owner manager that the pane has started to move 3268 if self._owner_mgr: 3269 if self._owner_mgr._from_move: 3270 return 3271 self._owner_mgr._action_window = self._pane_window 3272 point = wx.GetMousePosition() 3273 action_offset = point - self.GetPosition() 3274 3275 if self._is_toolbar: 3276 self._owner_mgr._toolbar_action_offset = action_offset 3277 self._owner_mgr.OnMotion_DragToolbarPane(point) 3278 else: 3279 self._owner_mgr._action_offset = action_offset 3280 self._owner_mgr.OnMotion_DragFloatingPane(point)
3281 3282
3283 - def OnMoving(self, rect, direction):
3284 """ 3285 The user is moving the floating pane. 3286 3287 :param Rect `rect`: the pane client rectangle; 3288 :param integer `direction`: the direction in which the pane is moving, can be one of 3289 ``wx.NORTH``, ``wx.SOUTH``, ``wx.EAST`` or ``wx.WEST``. 3290 3291 .. note:: 3292 3293 This event is only processed on wxMAC if :class:`AuiManager` is using the 3294 ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. 3295 """ 3296 3297 # notify the owner manager that the pane is moving 3298 self.OnMoveStart(None) 3299 self._lastDirection = direction
3300 3301
3302 - def OnMoveFinished(self):
3303 """ 3304 The user has just finished moving the floating pane. 3305 3306 .. note:: 3307 3308 This method is used only on wxMAC if :class:`AuiManager` is using the 3309 ``AUI_MGR_USE_NATIVE_MINIFRAMES`` style. 3310 3311 """ 3312 3313 # notify the owner manager that the pane has finished moving 3314 if self._owner_mgr: 3315 self._owner_mgr._action_window = self._pane_window 3316 point = wx.GetMousePosition() 3317 if self._is_toolbar: 3318 self._owner_mgr.OnLeftUp_DragToolbarPane(point) 3319 else: 3320 self._owner_mgr.OnLeftUp_DragFloatingPane(point) 3321 3322 self._owner_mgr.OnFloatingPaneMoved(self._pane_window, point)
3323 3324
3325 - def OnCheckFlyTimer(self, event):
3326 """ 3327 Handles the ``wx.EVT_TIMER`` event for :class:`AuiFloatingFrame`. 3328 3329 :param `event`: a :class:`TimerEvent` to be processed. 3330 3331 :note: This is used solely for "fly-out" panes. 3332 """ 3333 3334 if self._owner_mgr: 3335 pane = self._mgr.GetPane(self._pane_window) 3336 if pane.IsFlyOut(): 3337 if self.IsShownOnScreen(): 3338 self.FlyOut()
3339 3340
3341 - def OnFindManager(self, event):
3342 """ 3343 Handles the ``EVT_AUI_FIND_MANAGER`` event for :class:`AuiFloatingFrame`. 3344 3345 :param `event`: a :class:`AuiManagerEvent` event to be processed. 3346 """ 3347 3348 event.SetManager(self._owner_mgr)
3349 3350
3351 - def FlyOut(self):
3352 """ Starts the flying in and out of a floating pane. """ 3353 3354 if self._fly_timer.IsRunning(): 3355 return 3356 3357 if _VERSION_STRING < "2.9": 3358 leftDown = wx.GetMouseState().LeftDown() 3359 else: 3360 leftDown = wx.GetMouseState().LeftIsDown() 3361 3362 if leftDown: 3363 return 3364 3365 rect = wx.Rect(*self.GetScreenRect()) 3366 rect.Inflate(10, 10) 3367 3368 if rect.Contains(wx.GetMousePosition()): 3369 if not self._fly: 3370 return 3371 self._send_size = False 3372 self._fly_timer.Start(5) 3373 else: 3374 if self._fly: 3375 return 3376 self._send_size = False 3377 self._fly_timer.Start(5)
3378 3379
3380 - def OnFlyTimer(self, event):
3381 """ 3382 Handles the ``wx.EVT_TIMER`` event for :class:`AuiFloatingFrame`. 3383 3384 :param `event`: a :class:`TimerEvent` to be processed. 3385 """ 3386 3387 current_size = self.GetClientSize() 3388 floating_size = wx.Size(*self._owner_mgr.GetPane(self._pane_window).floating_size) 3389 3390 if floating_size.y == -1: 3391 floating_size = self._floating_size 3392 3393 if not self._fly: 3394 min_size = self._mgr.GetArtProvider().GetMetric(AUI_DOCKART_CAPTION_SIZE) 3395 3396 if wx.Platform != "__WXMSW__": 3397 min_size += 2*wx.SystemSettings.GetMetric(wx.SYS_EDGE_Y) 3398 3399 if current_size.y - self._fly_step <= min_size: 3400 self.SetClientSize((current_size.x, min_size)) 3401 self._fly = True 3402 self._fly_timer.Stop() 3403 self._send_size = True 3404 else: 3405 self.SetClientSize((current_size.x, current_size.y-self._fly_step)) 3406 3407 else: 3408 if current_size.y + self._fly_step >= floating_size.y: 3409 self.SetClientSize((current_size.x, floating_size.y)) 3410 self._fly = False 3411 self._fly_timer.Stop() 3412 self._send_size = True 3413 else: 3414 self.SetClientSize((current_size.x, current_size.y+self._fly_step)) 3415 3416 self.Update() 3417 self.Refresh()
3418 3419
3420 - def FadeOut(self):
3421 """ Actually starts the fading out of the floating pane. """ 3422 3423 while 1: 3424 self._alpha_amount -= 10 3425 if self._alpha_amount <= 0: 3426 self._alpha_amount = 255 3427 return 3428 3429 self.SetTransparent(self._alpha_amount) 3430 wx.SafeYield() 3431 wx.MilliSleep(15)
3432 3433 3434 # -- static utility functions -- 3435
3436 -def DrawResizeHint(dc, rect):
3437 """ 3438 Draws a resize hint while a sash is dragged. 3439 3440 :param Rect `rect`: a rectangle which specifies the sash dimensions. 3441 """ 3442 3443 if wx.Platform == "__WXMSW__" and wx.App.GetComCtl32Version() >= 600: 3444 if wx.GetOsVersion()[1] > 5: 3445 # Windows Vista 3446 dc.SetPen(wx.Pen("black", 2, wx.SOLID)) 3447 dc.SetBrush(wx.TRANSPARENT_BRUSH) 3448 else: 3449 # Draw the nice XP style splitter 3450 dc.SetPen(wx.TRANSPARENT_PEN) 3451 dc.SetBrush(wx.BLACK_BRUSH) 3452 dc.SetLogicalFunction(wx.INVERT) 3453 dc.DrawRectangleRect(rect) 3454 dc.SetLogicalFunction(wx.COPY) 3455 else: 3456 stipple = PaneCreateStippleBitmap() 3457 brush = wx.BrushFromBitmap(stipple) 3458 dc.SetBrush(brush) 3459 dc.SetPen(wx.TRANSPARENT_PEN) 3460 3461 dc.SetLogicalFunction(wx.XOR) 3462 dc.DrawRectangleRect(rect)
3463 3464
3465 -def CopyDocksAndPanes(src_docks, src_panes):
3466 """ 3467 This utility function creates shallow copies of 3468 the dock and pane info. :class:`AuiManager` usually contain pointers 3469 to :class:`AuiPaneInfo` classes, thus this function is necessary to reliably 3470 reconstruct that relationship in the new dock info and pane info arrays. 3471 3472 :param `src_docks`: a list of :class:`AuiDockInfo` classes; 3473 :param `src_panes`: a list of :class:`AuiPaneInfo` classes. 3474 """ 3475 3476 dest_docks = src_docks 3477 dest_panes = src_panes 3478 3479 for ii in xrange(len(dest_docks)): 3480 dock = dest_docks[ii] 3481 for jj in xrange(len(dock.panes)): 3482 for kk in xrange(len(src_panes)): 3483 if dock.panes[jj] == src_panes[kk]: 3484 dock.panes[jj] = dest_panes[kk] 3485 3486 return dest_docks, dest_panes
3487 3488
3489 -def CopyDocksAndPanes2(src_docks, src_panes):
3490 """ 3491 This utility function creates full copies of 3492 the dock and pane info. :class:`AuiManager` usually contain pointers 3493 to :class:`AuiPaneInfo` classes, thus this function is necessary to reliably 3494 reconstruct that relationship in the new dock info and pane info arrays. 3495 3496 :param `src_docks`: a list of :class:`AuiDockInfo` classes; 3497 :param `src_panes`: a list of :class:`AuiPaneInfo` classes. 3498 """ 3499 3500 dest_docks = [] 3501 3502 for ii in xrange(len(src_docks)): 3503 dest_docks.append(AuiDockInfo()) 3504 dest_docks[ii].dock_direction = src_docks[ii].dock_direction 3505 dest_docks[ii].dock_layer = src_docks[ii].dock_layer 3506 dest_docks[ii].dock_row = src_docks[ii].dock_row 3507 dest_docks[ii].size = src_docks[ii].size 3508 dest_docks[ii].min_size = src_docks[ii].min_size 3509 dest_docks[ii].resizable = src_docks[ii].resizable 3510 dest_docks[ii].fixed = src_docks[ii].fixed 3511 dest_docks[ii].toolbar = src_docks[ii].toolbar 3512 dest_docks[ii].panes = src_docks[ii].panes 3513 dest_docks[ii].rect = wx.Rect(*src_docks[ii].rect) 3514 3515 dest_panes = [] 3516 3517 for ii in xrange(len(src_panes)): 3518 dest_panes.append(AuiPaneInfo()) 3519 dest_panes[ii].name = src_panes[ii].name 3520 dest_panes[ii].caption = src_panes[ii].caption 3521 dest_panes[ii].window = src_panes[ii].window 3522 dest_panes[ii].frame = src_panes[ii].frame 3523 dest_panes[ii].state = src_panes[ii].state 3524 dest_panes[ii].dock_direction = src_panes[ii].dock_direction 3525 dest_panes[ii].dock_layer = src_panes[ii].dock_layer 3526 dest_panes[ii].dock_row = src_panes[ii].dock_row 3527 dest_panes[ii].dock_pos = src_panes[ii].dock_pos 3528 dest_panes[ii].best_size = wx.Size(*src_panes[ii].best_size) 3529 dest_panes[ii].min_size = wx.Size(*src_panes[ii].min_size) 3530 dest_panes[ii].max_size = wx.Size(*src_panes[ii].max_size) 3531 dest_panes[ii].floating_pos = wx.Point(*src_panes[ii].floating_pos) 3532 dest_panes[ii].floating_size = wx.Size(*src_panes[ii].floating_size) 3533 dest_panes[ii].dock_proportion = src_panes[ii].dock_proportion 3534 dest_panes[ii].buttons = src_panes[ii].buttons 3535 dest_panes[ii].rect = wx.Rect(*src_panes[ii].rect) 3536 dest_panes[ii].icon = src_panes[ii].icon 3537 dest_panes[ii].notebook_id = src_panes[ii].notebook_id 3538 dest_panes[ii].transparent = src_panes[ii].transparent 3539 dest_panes[ii].snapped = src_panes[ii].snapped 3540 dest_panes[ii].minimize_mode = src_panes[ii].minimize_mode 3541 dest_panes[ii].minimize_target = src_panes[ii].minimize_target 3542 3543 for ii in xrange(len(dest_docks)): 3544 dock = dest_docks[ii] 3545 for jj in xrange(len(dock.panes)): 3546 for kk in xrange(len(src_panes)): 3547 if dock.panes[jj] == src_panes[kk]: 3548 dock.panes[jj] = dest_panes[kk] 3549 3550 dest_docks[ii] = dock 3551 3552 return dest_docks, dest_panes
3553 3554
3555 -def GetMaxLayer(docks, dock_direction):
3556 """ 3557 This is an internal function which returns 3558 the highest layer inside the specified dock. 3559 3560 :param `docks`: a list of :class:`AuiDockInfo`; 3561 :param `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze. 3562 """ 3563 3564 max_layer = 0 3565 3566 for dock in docks: 3567 if dock.dock_direction == dock_direction and dock.dock_layer > max_layer and not dock.fixed: 3568 max_layer = dock.dock_layer 3569 3570 return max_layer
3571 3572
3573 -def GetMaxRow(panes, dock_direction, dock_layer):
3574 """ 3575 This is an internal function which returns 3576 the highest layer inside the specified dock. 3577 3578 :param `panes`: a list of :class:`AuiPaneInfo`; 3579 :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze; 3580 :param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze. 3581 """ 3582 3583 max_row = 0 3584 3585 for pane in panes: 3586 if pane.dock_direction == dock_direction and pane.dock_layer == dock_layer and \ 3587 pane.dock_row > max_row: 3588 max_row = pane.dock_row 3589 3590 return max_row
3591 3592
3593 -def DoInsertDockLayer(panes, dock_direction, dock_layer):
3594 """ 3595 This is an internal function that inserts a new dock 3596 layer by incrementing all existing dock layer values by one. 3597 3598 :param `panes`: a list of :class:`AuiPaneInfo`; 3599 :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze; 3600 :param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze. 3601 """ 3602 3603 for ii in xrange(len(panes)): 3604 pane = panes[ii] 3605 if not pane.IsFloating() and pane.dock_direction == dock_direction and pane.dock_layer >= dock_layer: 3606 pane.dock_layer = pane.dock_layer + 1 3607 3608 panes[ii] = pane 3609 3610 return panes
3611 3612
3613 -def DoInsertDockRow(panes, dock_direction, dock_layer, dock_row):
3614 """ 3615 This is an internal function that inserts a new dock 3616 row by incrementing all existing dock row values by one. 3617 3618 :param `panes`: a list of :class:`AuiPaneInfo`; 3619 :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze; 3620 :param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze; 3621 :param integer `dock_row`: the :class:`AuiDockInfo` row to analyze. 3622 """ 3623 3624 for pane in panes: 3625 if not pane.IsFloating() and pane.dock_direction == dock_direction and \ 3626 pane.dock_layer == dock_layer and pane.dock_row >= dock_row: 3627 pane.dock_row += 1 3628 3629 return panes
3630 3631
3632 -def DoInsertPane(panes, dock_direction, dock_layer, dock_row, dock_pos):
3633 """ 3634 This is an internal function that inserts a new pane 3635 by incrementing all existing dock position values by one. 3636 3637 :param `panes`: a list of :class:`AuiPaneInfo`; 3638 :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze; 3639 :param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze. 3640 :param integer `dock_row`: the :class:`AuiDockInfo` row to analyze; 3641 :param integer `dock_pos`: the :class:`AuiDockInfo` position to analyze. 3642 """ 3643 3644 for ii in xrange(len(panes)): 3645 pane = panes[ii] 3646 if not pane.IsFloating() and pane.dock_direction == dock_direction and \ 3647 pane.dock_layer == dock_layer and pane.dock_row == dock_row and \ 3648 pane.dock_pos >= dock_pos: 3649 pane.dock_pos = pane.dock_pos + 1 3650 3651 panes[ii] = pane 3652 3653 return panes
3654 3655
3656 -def FindDocks(docks, dock_direction, dock_layer=-1, dock_row=-1, reverse=False):
3657 """ 3658 This is an internal function that returns a list of docks which meet 3659 the specified conditions in the parameters and returns a sorted array 3660 (sorted by layer and then row). 3661 3662 :param `docks`: a list of :class:`AuiDockInfo`; 3663 :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze; 3664 :param integer `dock_layer`: the :class:`AuiDockInfo` layer to analyze. 3665 :param integer `dock_row`: the :class:`AuiDockInfo` row to analyze; 3666 """ 3667 3668 matchDocks = [(d.dock_layer, d.dock_row, d.dock_direction, d) for d in docks if \ 3669 (dock_direction == -1 or dock_direction == d.dock_direction) and \ 3670 ((dock_layer == -1 or dock_layer == d.dock_layer) and \ 3671 (dock_row == -1 or dock_row == d.dock_row))] 3672 3673 arr = [x[-1] for x in sorted(matchDocks, reverse=reverse)] 3674 3675 return arr
3676 3677
3678 -def FindOppositeDocks(docks, dock_direction):
3679 """ 3680 This is an internal function that returns a list of docks 3681 which is related to the opposite direction. 3682 3683 :param `docks`: a list of :class:`AuiDockInfo`; 3684 :param integer `dock_direction`: the :class:`AuiDockInfo` docking direction to analyze; 3685 """ 3686 3687 if dock_direction == AUI_DOCK_LEFT: 3688 arr = FindDocks(docks, AUI_DOCK_RIGHT, -1, -1) 3689 elif dock_direction == AUI_DOCK_TOP: 3690 arr = FindDocks(docks, AUI_DOCK_BOTTOM, -1, -1) 3691 elif dock_direction == AUI_DOCK_RIGHT: 3692 arr = FindDocks(docks, AUI_DOCK_LEFT, -1, -1) 3693 elif dock_direction == AUI_DOCK_BOTTOM: 3694 arr = FindDocks(docks, AUI_DOCK_TOP, -1, -1) 3695 3696 return arr
3697 3698
3699 -def FindPaneInDock(dock, window):
3700 """ 3701 This method looks up a specified window pointer inside a dock. 3702 If found, the corresponding :class:`AuiDockInfo` pointer is returned, otherwise ``None``. 3703 3704 :param `dock`: a :class:`AuiDockInfo` structure; 3705 :param Window `window`: the window associated to the pane we are seeking. 3706 """ 3707 3708 for p in dock.panes: 3709 if p.window == window: 3710 return p 3711 3712 return None
3713 3714
3715 -def GetToolBarDockOffsets(docks):
3716 """ 3717 Returns the toolbar dock offsets (top-left and bottom-right). 3718 3719 :param `docks`: a list of :class:`AuiDockInfo` to analyze. 3720 """ 3721 3722 top_left = wx.Size(0, 0) 3723 bottom_right = wx.Size(0, 0) 3724 3725 for dock in docks: 3726 if dock.toolbar: 3727 dock_direction = dock.dock_direction 3728 if dock_direction == AUI_DOCK_LEFT: 3729 top_left.x += dock.rect.width 3730 bottom_right.x += dock.rect.width 3731 3732 elif dock_direction == AUI_DOCK_TOP: 3733 top_left.y += dock.rect.height 3734 bottom_right.y += dock.rect.height 3735 3736 elif dock_direction == AUI_DOCK_RIGHT: 3737 bottom_right.x += dock.rect.width 3738 3739 elif dock_direction == AUI_DOCK_BOTTOM: 3740 bottom_right.y += dock.rect.height 3741 3742 return top_left, bottom_right
3743 3744
3745 -def GetInternalFrameRect(window, docks):
3746 """ 3747 Returns the window rectangle excluding toolbars. 3748 3749 :param `window`: a :class:`Window` derived window; 3750 :param `docks`: a list of :class:`AuiDockInfo` structures. 3751 """ 3752 3753 frameRect = wx.Rect() 3754 3755 frameRect.SetTopLeft(window.ClientToScreen(window.GetClientAreaOrigin())) 3756 frameRect.SetSize(window.GetClientSize()) 3757 3758 top_left, bottom_right = GetToolBarDockOffsets(docks) 3759 3760 # make adjustments for toolbars 3761 frameRect.x += top_left.x 3762 frameRect.y += top_left.y 3763 frameRect.width -= bottom_right.x 3764 frameRect.height -= bottom_right.y 3765 3766 return frameRect
3767 3768
3769 -def CheckOutOfWindow(window, pt):
3770 """ 3771 Checks if a point is outside the window rectangle. 3772 3773 :param `window`: a :class:`Window` derived window; 3774 :param `pt`: a :class:`Point` object. 3775 """ 3776 3777 auiWindowMargin = 30 3778 marginRect = wx.Rect(*window.GetClientRect()) 3779 marginRect.Inflate(auiWindowMargin, auiWindowMargin) 3780 3781 return not marginRect.Contains(pt)
3782 3783
3784 -def CheckEdgeDrop(window, docks, pt):
3785 """ 3786 Checks on which edge of a window the drop action has taken place. 3787 3788 :param `window`: a :class:`Window` derived window; 3789 :param `docks`: a list of :class:`AuiDockInfo` structures; 3790 :param `pt`: a :class:`Point` object. 3791 """ 3792 3793 screenPt = window.ClientToScreen(pt) 3794 clientSize = window.GetClientSize() 3795 frameRect = GetInternalFrameRect(window, docks) 3796 3797 if screenPt.y >= frameRect.GetTop() and screenPt.y < frameRect.GetBottom(): 3798 if pt.x < auiLayerInsertOffset and pt.x > auiLayerInsertOffset - auiLayerInsertPixels: 3799 return wx.LEFT 3800 3801 if pt.x >= clientSize.x - auiLayerInsertOffset and \ 3802 pt.x < clientSize.x - auiLayerInsertOffset + auiLayerInsertPixels: 3803 return wx.RIGHT 3804 3805 if screenPt.x >= frameRect.GetLeft() and screenPt.x < frameRect.GetRight(): 3806 if pt.y < auiLayerInsertOffset and pt.y > auiLayerInsertOffset - auiLayerInsertPixels: 3807 return wx.TOP 3808 3809 if pt.y >= clientSize.y - auiLayerInsertOffset and \ 3810 pt.y < clientSize.y - auiLayerInsertOffset + auiLayerInsertPixels: 3811 return wx.BOTTOM 3812 3813 return -1
3814 3815
3816 -def RemovePaneFromDocks(docks, pane, exc=None):
3817 """ 3818 Removes a pane window from all docks 3819 with a possible exception specified by parameter `exc`. 3820 3821 :param `docks`: a list of :class:`AuiDockInfo` structures; 3822 :param AuiPaneInfo `pane`: the pane to be removed; 3823 :param AuiPaneInfo `exc`: the possible pane exception. 3824 """ 3825 3826 for ii in xrange(len(docks)): 3827 d = docks[ii] 3828 if d == exc: 3829 continue 3830 pi = FindPaneInDock(d, pane.window) 3831 if pi: 3832 d.panes.remove(pi) 3833 3834 docks[ii] = d 3835 3836 return docks
3837 3838
3839 -def RenumberDockRows(docks):
3840 """ 3841 Takes a dock and assigns sequential numbers 3842 to existing rows. Basically it takes out the gaps so if a 3843 dock has rows with numbers 0, 2, 5, they will become 0, 1, 2. 3844 3845 :param `docks`: a list of :class:`AuiDockInfo` structures. 3846 """ 3847 3848 for ii in xrange(len(docks)): 3849 dock = docks[ii] 3850 dock.dock_row = ii 3851 for jj in xrange(len(dock.panes)): 3852 dock.panes[jj].dock_row = ii 3853 3854 docks[ii] = dock 3855 3856 return docks
3857 3858
3859 -def SetActivePane(panes, active_pane):
3860 """ 3861 Sets the active pane, as well as cycles through 3862 every other pane and makes sure that all others' active flags 3863 are turned off. 3864 3865 :param `panes`: a list of :class:`AuiPaneInfo` structures; 3866 :param AuiPaneInfo `active_pane`: the pane to be made active (if found). 3867 """ 3868 3869 for pane in panes: 3870 pane.state &= ~AuiPaneInfo.optionActive 3871 3872 for pane in panes: 3873 if pane.window == active_pane and not pane.IsNotebookPage(): 3874 pane.state |= AuiPaneInfo.optionActive 3875 return True, panes 3876 3877 return False, panes
3878 3879
3880 -def ShowDockingGuides(guides, show):
3881 """ 3882 Shows or hide the docking guide windows. 3883 3884 :param `guides`: a list of :class:`AuiDockingGuide` classes; 3885 :param bool `show`: whether to show or hide the docking guide windows. 3886 """ 3887 3888 for target in guides: 3889 3890 if show and not target.host.IsShown(): 3891 target.host.Show() 3892 target.host.Update() 3893 3894 elif not show and target.host.IsShown(): 3895 target.host.Hide()
3896 3897
3898 -def RefreshDockingGuides(guides):
3899 """ 3900 Refreshes the docking guide windows. 3901 3902 :param `guides`: a list of :class:`AuiDockingGuide` classes; 3903 """ 3904 3905 for target in guides: 3906 if target.host.IsShown(): 3907 target.host.Refresh()
3908 3909
3910 -def PaneSortFunc(p1, p2):
3911 """ 3912 This function is used to sort panes by dock position. 3913 3914 :param AuiPaneInfo `p1`: the first pane instance to compare; 3915 :param AuiPaneInfo `p2`: the second pane instance to compare. 3916 """ 3917 3918 return (p1.dock_pos < p2.dock_pos and [-1] or [1])[0]
3919 3920
3921 -def GetNotebookRoot(panes, notebook_id):
3922 """ 3923 Returns the :class:`~lib.agw.aui.auibook.AuiNotebook` which has the specified `notebook_id`. 3924 3925 :param `panes`: a list of :class:`AuiPaneInfo` instances; 3926 :param integer `notebook_id`: the target notebook id. 3927 """ 3928 3929 for paneInfo in panes: 3930 if paneInfo.IsNotebookControl() and paneInfo.notebook_id == notebook_id: 3931 return paneInfo 3932 3933 return None
3934 3935
3936 -def EscapeDelimiters(s):
3937 """ 3938 Changes ``;`` into ``\`` and ``|`` into ``\|`` in the input string. 3939 3940 :param string `s`: the string to be analyzed. 3941 3942 :note: This is an internal functions which is used for saving perspectives. 3943 """ 3944 3945 result = s.replace(";", "\\") 3946 result = result.replace("|", "|\\") 3947 3948 return result
3949 3950
3951 -def IsDifferentDockingPosition(pane1, pane2):
3952 """ 3953 Returns whether `pane1` and `pane2` are in a different docking position 3954 based on pane status, docking direction, docking layer and docking row. 3955 3956 :param `pane1`: a :class:`AuiPaneInfo` instance; 3957 :param `pane2`: another :class:`AuiPaneInfo` instance. 3958 """ 3959 3960 return pane1.IsFloating() != pane2.IsFloating() or \ 3961 pane1.dock_direction != pane2.dock_direction or \ 3962 pane1.dock_layer != pane2.dock_layer or \ 3963 pane1.dock_row != pane2.dock_row
3964 3965 3966 # Convenience function
3967 -def AuiManager_HasLiveResize(manager):
3968 """ 3969 Static function which returns if the input `manager` should have "live resize" 3970 behaviour. 3971 3972 :param `manager`: an instance of :class:`AuiManager`. 3973 3974 .. note:: 3975 3976 This method always returns ``True`` on wxMAC as this platform doesn't have 3977 the ability to use :class:`ScreenDC` to draw sashes. 3978 3979 """ 3980 3981 # With Core Graphics on Mac, it's not possible to show sash feedback, 3982 # so we'll always use live update instead. 3983 3984 if wx.Platform == "__WXMAC__": 3985 return True 3986 else: 3987 return (manager.GetAGWFlags() & AUI_MGR_LIVE_RESIZE) == AUI_MGR_LIVE_RESIZE
3988 3989 3990 # Convenience function
3991 -def AuiManager_UseNativeMiniframes(manager):
3992 """ 3993 Static function which returns if the input `manager` should use native :class:`MiniFrame` as 3994 floating panes. 3995 3996 :param `manager`: an instance of :class:`AuiManager`. 3997 3998 .. note:: 3999 4000 This method always returns ``True`` on wxMAC as this platform doesn't have 4001 the ability to use custom drawn miniframes. 4002 4003 """ 4004 4005 # With Core Graphics on Mac, it's not possible to show sash feedback, 4006 # so we'll always use live update instead. 4007 4008 if wx.Platform == "__WXMAC__": 4009 return True 4010 else: 4011 return (manager.GetAGWFlags() & AUI_MGR_USE_NATIVE_MINIFRAMES) == AUI_MGR_USE_NATIVE_MINIFRAMES
4012 4013
4014 -def GetManager(window):
4015 """ 4016 This function will return the aui manager for a given window. 4017 4018 :param Window `window`: this parameter should be any child window or grand-child 4019 window (and so on) of the frame/window managed by :class:`AuiManager`. The window 4020 does not need to be managed by the manager itself, nor does it even need 4021 to be a child or sub-child of a managed window. It must however be inside 4022 the window hierarchy underneath the managed window. 4023 """ 4024 4025 if not isinstance(wx.GetTopLevelParent(window), AuiFloatingFrame): 4026 if isinstance(window, auibar.AuiToolBar): 4027 return window.GetAuiManager() 4028 4029 evt = AuiManagerEvent(wxEVT_AUI_FIND_MANAGER) 4030 evt.SetManager(None) 4031 evt.ResumePropagation(wx.EVENT_PROPAGATE_MAX) 4032 4033 if not window.GetEventHandler().ProcessEvent(evt): 4034 return None 4035 4036 return evt.GetManager()
4037 4038 4039 # ---------------------------------------------------------------------------- # 4040
4041 -class AuiManager(wx.EvtHandler):
4042 """ 4043 AuiManager manages the panes associated with it for a particular :class:`Frame`, 4044 using a pane's :class:`AuiManager` information to determine each pane's docking and 4045 floating behavior. :class:`AuiManager` uses wxPython's sizer mechanism to plan the 4046 layout of each frame. It uses a replaceable dock art class to do all drawing, 4047 so all drawing is localized in one area, and may be customized depending on an 4048 applications' specific needs. 4049 4050 :class:`AuiManager` works as follows: the programmer adds panes to the class, or makes 4051 changes to existing pane properties (dock position, floating state, show state, etc...). 4052 To apply these changes, the :meth:`AuiManager.Update() <AuiManager.Update>` function is called. This batch 4053 processing can be used to avoid flicker, by modifying more than one pane at a time, 4054 and then "committing" all of the changes at once by calling `Update()`. 4055 4056 Panes can be added quite easily:: 4057 4058 text1 = wx.TextCtrl(self, -1) 4059 text2 = wx.TextCtrl(self, -1) 4060 self._mgr.AddPane(text1, AuiPaneInfo().Left().Caption("Pane Number One")) 4061 self._mgr.AddPane(text2, AuiPaneInfo().Bottom().Caption("Pane Number Two")) 4062 4063 self._mgr.Update() 4064 4065 4066 Later on, the positions can be modified easily. The following will float an 4067 existing pane in a tool window:: 4068 4069 self._mgr.GetPane(text1).Float() 4070 4071 4072 **Layers, Rows and Directions, Positions:** 4073 4074 Inside AUI, the docking layout is figured out by checking several pane parameters. 4075 Four of these are important for determining where a pane will end up. 4076 4077 **Direction** - Each docked pane has a direction, `Top`, `Bottom`, `Left`, `Right`, or `Center`. 4078 This is fairly self-explanatory. The pane will be placed in the location specified 4079 by this variable. 4080 4081 **Position** - More than one pane can be placed inside of a "dock". Imagine two panes 4082 being docked on the left side of a window. One pane can be placed over another. 4083 In proportionally managed docks, the pane position indicates it's sequential position, 4084 starting with zero. So, in our scenario with two panes docked on the left side, the 4085 top pane in the dock would have position 0, and the second one would occupy position 1. 4086 4087 **Row** - A row can allow for two docks to be placed next to each other. One of the most 4088 common places for this to happen is in the toolbar. Multiple toolbar rows are allowed, 4089 the first row being in row 0, and the second in row 1. Rows can also be used on 4090 vertically docked panes. 4091 4092 **Layer** - A layer is akin to an onion. Layer 0 is the very center of the managed pane. 4093 Thus, if a pane is in layer 0, it will be closest to the center window (also sometimes 4094 known as the "content window"). Increasing layers "swallow up" all layers of a lower 4095 value. This can look very similar to multiple rows, but is different because all panes 4096 in a lower level yield to panes in higher levels. The best way to understand layers 4097 is by running the AUI sample (`AUI.py`). 4098 """ 4099
4100 - def __init__(self, managed_window=None, agwFlags=None):
4101 """ 4102 Default class constructor. 4103 4104 :param Window `managed_window`: specifies the window which should be managed; 4105 :param integer `agwFlags`: specifies options which allow the frame management behavior to be 4106 modified. `agwFlags` can be a combination of the following style bits: 4107 4108 ==================================== ================================== 4109 Flag name Description 4110 ==================================== ================================== 4111 ``AUI_MGR_ALLOW_FLOATING`` Allow floating of panes 4112 ``AUI_MGR_ALLOW_ACTIVE_PANE`` If a pane becomes active, "highlight" it in the interface 4113 ``AUI_MGR_TRANSPARENT_DRAG`` If the platform supports it, set transparency on a floating pane while it is dragged by the user 4114 ``AUI_MGR_TRANSPARENT_HINT`` If the platform supports it, show a transparent hint window when the user is about to dock a floating pane 4115 ``AUI_MGR_VENETIAN_BLINDS_HINT`` Show a "venetian blind" effect when the user is about to dock a floating pane 4116 ``AUI_MGR_RECTANGLE_HINT`` Show a rectangle hint effect when the user is about to dock a floating pane 4117 ``AUI_MGR_HINT_FADE`` If the platform supports it, the hint window will fade in and out 4118 ``AUI_MGR_NO_VENETIAN_BLINDS_FADE`` Disables the "venetian blind" fade in and out 4119 ``AUI_MGR_LIVE_RESIZE`` Live resize when the user drag a sash 4120 ``AUI_MGR_ANIMATE_FRAMES`` Fade-out floating panes when they are closed (all platforms which support frames transparency) 4121 and show a moving rectangle when they are docked (Windows < Vista and GTK only) 4122 ``AUI_MGR_AERO_DOCKING_GUIDES`` Use the new Aero-style bitmaps as docking guides 4123 ``AUI_MGR_PREVIEW_MINIMIZED_PANES`` Slide in and out minimized panes to preview them 4124 ``AUI_MGR_WHIDBEY_DOCKING_GUIDES`` Use the new Whidbey-style bitmaps as docking guides 4125 ``AUI_MGR_SMOOTH_DOCKING`` Performs a "smooth" docking of panes (a la PyQT) 4126 ``AUI_MGR_USE_NATIVE_MINIFRAMES`` Use miniframes with native caption bar as floating panes instead or custom drawn caption bars (forced on wxMAC) 4127 ``AUI_MGR_AUTONB_NO_CAPTION`` Panes that merge into an automatic notebook will not have the pane caption visible 4128 ==================================== ================================== 4129 4130 Default value for `agwFlags` is: 4131 ``AUI_MGR_DEFAULT`` = ``AUI_MGR_ALLOW_FLOATING`` | ``AUI_MGR_TRANSPARENT_HINT`` | ``AUI_MGR_HINT_FADE`` | ``AUI_MGR_NO_VENETIAN_BLINDS_FADE`` 4132 4133 .. note:: 4134 4135 If using the ``AUI_MGR_USE_NATIVE_MINIFRAMES``, double-clicking on a 4136 floating pane caption will not re-dock the pane, but simply maximize it (if 4137 :meth:`AuiPaneInfo.MaximizeButton` has been set to ``True``) or do nothing. 4138 4139 """ 4140 4141 wx.EvtHandler.__init__(self) 4142 4143 self._action = actionNone 4144 self._action_window = None 4145 self._hover_button = None 4146 self._art = dockart.AuiDefaultDockArt() 4147 self._hint_window = None 4148 self._active_pane = None 4149 self._has_maximized = False 4150 self._has_minimized = False 4151 4152 self._frame = None 4153 self._dock_constraint_x = 0.3 4154 self._dock_constraint_y = 0.3 4155 self._reserved = None 4156 4157 self._panes = [] 4158 self._docks = [] 4159 self._uiparts = [] 4160 4161 self._guides = [] 4162 self._notebooks = [] 4163 4164 self._masterManager = None 4165 self._currentDragItem = -1 4166 self._lastknowndocks = {} 4167 4168 self._hint_fadetimer = wx.Timer(self, wx.ID_ANY) 4169 self._hint_fademax = 50 4170 self._last_hint = wx.Rect() 4171 4172 self._from_move = False 4173 self._last_rect = wx.Rect() 4174 4175 if agwFlags is None: 4176 agwFlags = AUI_MGR_DEFAULT 4177 4178 self._agwFlags = agwFlags 4179 self._is_docked = (False, wx.RIGHT, wx.TOP, 0) 4180 self._snap_limits = (15, 15) 4181 4182 if wx.Platform == "__WXMSW__": 4183 self._animation_step = 30.0 4184 else: 4185 self._animation_step = 5.0 4186 4187 self._hint_rect = wx.Rect() 4188 4189 self._preview_timer = wx.Timer(self, wx.ID_ANY) 4190 self._sliding_frame = None 4191 4192 self._autoNBTabArt = tabart.AuiDefaultTabArt() 4193 self._autoNBStyle = AUI_NB_DEFAULT_STYLE | AUI_NB_BOTTOM | \ 4194 AUI_NB_SUB_NOTEBOOK | AUI_NB_TAB_EXTERNAL_MOVE 4195 self._autoNBStyle -= AUI_NB_DRAW_DND_TAB 4196 4197 if managed_window: 4198 self.SetManagedWindow(managed_window) 4199 4200 self.Bind(wx.EVT_PAINT, self.OnPaint) 4201 self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) 4202 self.Bind(wx.EVT_SIZE, self.OnSize) 4203 self.Bind(wx.EVT_SET_CURSOR, self.OnSetCursor) 4204 self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) 4205 self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick) 4206 self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) 4207 self.Bind(wx.EVT_MOTION, self.OnMotion) 4208 self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow) 4209 self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus) 4210 self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLost) 4211 self.Bind(wx.EVT_TIMER, self.OnHintFadeTimer, self._hint_fadetimer) 4212 self.Bind(wx.EVT_TIMER, self.SlideIn, self._preview_timer) 4213 self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy) 4214 4215 self.Bind(wx.EVT_MOVE, self.OnMove) 4216 self.Bind(wx.EVT_SYS_COLOUR_CHANGED, self.OnSysColourChanged) 4217 4218 self.Bind(EVT_AUI_PANE_BUTTON, self.OnPaneButton) 4219 self.Bind(EVT_AUI_RENDER, self.OnRender) 4220 self.Bind(EVT_AUI_FIND_MANAGER, self.OnFindManager) 4221 self.Bind(EVT_AUI_PANE_MIN_RESTORE, self.OnRestoreMinimizedPane) 4222 self.Bind(EVT_AUI_PANE_DOCKED, self.OnPaneDocked) 4223 4224 self.Bind(auibook.EVT_AUINOTEBOOK_BEGIN_DRAG, self.OnTabBeginDrag) 4225 self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnTabPageClose) 4226 self.Bind(auibook.EVT_AUINOTEBOOK_PAGE_CHANGED, self.OnTabSelected)
4227 4228
4229 - def CreateFloatingFrame(self, parent, pane_info):
4230 """ 4231 Creates a floating frame for the windows. 4232 4233 :param Window `parent`: the floating frame parent; 4234 :param `pane_info`: the :class:`AuiPaneInfo` class with all the pane's information. 4235 """ 4236 4237 return AuiFloatingFrame(parent, self, pane_info)
4238 4239
4240 - def CanDockPanel(self, p):
4241 """ 4242 Returns whether a pane can be docked or not. 4243 4244 :param `p`: the :class:`AuiPaneInfo` class with all the pane's information. 4245 """ 4246 4247 # is the pane dockable? 4248 if not p.IsDockable(): 4249 return False 4250 4251 # if a key modifier is pressed while dragging the frame, 4252 # don't dock the window 4253 return not (wx.GetKeyState(wx.WXK_CONTROL) or wx.GetKeyState(wx.WXK_ALT))
4254 4255
4256 - def GetPaneByWidget(self, window):
4257 """ 4258 This version of :meth:`GetPane` looks up a pane based on a 'pane window'. 4259 4260 :param `window`: a :class:`Window` derived window. 4261 4262 :see: :meth:`~AuiManager.GetPane` 4263 """ 4264 4265 for p in self._panes: 4266 if p.window == window: 4267 return p 4268 4269 return NonePaneInfo
4270 4271
4272 - def GetPaneByName(self, name):
4273 """ 4274 This version of :meth:`GetPane` looks up a pane based on a 'pane name'. 4275 4276 :param string `name`: the pane name. 4277 4278 :see: :meth:`GetPane` 4279 """ 4280 4281 for p in self._panes: 4282 if p.name == name: 4283 return p 4284 4285 return NonePaneInfo
4286 4287
4288 - def GetPane(self, item):
4289 """ 4290 Looks up a :class:`AuiPaneInfo` structure based on the supplied window pointer. Upon failure, 4291 :meth:`GetPane` returns an empty :class:`AuiPaneInfo`, a condition which can be checked 4292 by calling :meth:`AuiPaneInfo.IsOk() <AuiPaneInfo.IsOk>`. 4293 4294 The pane info's structure may then be modified. Once a pane's info is modified, :meth:`Update` 4295 must be called to realize the changes in the UI. 4296 4297 :param `item`: either a pane name or a :class:`Window`. 4298 """ 4299 4300 if isinstance(item, basestring): 4301 return self.GetPaneByName(item) 4302 else: 4303 return self.GetPaneByWidget(item)
4304 4305
4306 - def GetAllPanes(self):
4307 """ Returns a reference to all the pane info structures. """ 4308 4309 return self._panes
4310 4311
4312 - def ShowPane(self, window, show):
4313 """ 4314 Shows or hides a pane based on the window passed as input. 4315 4316 :param Window `window`: any subclass or derivation of :class:`Window`; 4317 :param bool `show`: ``True`` to show the pane, ``False`` otherwise. 4318 """ 4319 4320 p = self.GetPane(window) 4321 4322 if p.IsOk(): 4323 if p.IsNotebookPage(): 4324 if show: 4325 4326 notebook = self._notebooks[p.notebook_id] 4327 id = notebook.GetPageIndex(p.window) 4328 if id >= 0: 4329 notebook.SetSelection(id) 4330 self.ShowPane(notebook, True) 4331 4332 else: 4333 p.Show(show) 4334 4335 if p.frame: 4336 p.frame.Raise() 4337 4338 self.Update()
4339 4340
4341 - def HitTest(self, x, y):
4342 """ 4343 This is an internal function which determines 4344 which UI item the specified coordinates are over. 4345 4346 :param integer `x`: specifies a x position in client coordinates; 4347 :param integer `y`: specifies a y position in client coordinates. 4348 """ 4349 4350 result = None 4351 4352 for item in self._uiparts: 4353 # we are not interested in typeDock, because this space 4354 # isn't used to draw anything, just for measurements 4355 # besides, the entire dock area is covered with other 4356 # rectangles, which we are interested in. 4357 if item.type == AuiDockUIPart.typeDock: 4358 continue 4359 4360 # if we already have a hit on a more specific item, we are not 4361 # interested in a pane hit. If, however, we don't already have 4362 # a hit, returning a pane hit is necessary for some operations 4363 if item.type in [AuiDockUIPart.typePane, AuiDockUIPart.typePaneBorder] and result: 4364 continue 4365 4366 # if the point is inside the rectangle, we have a hit 4367 if item.rect.Contains((x, y)): 4368 result = item 4369 4370 return result
4371 4372
4373 - def PaneHitTest(self, panes, pt):
4374 """ 4375 Similar to :meth:`HitTest`, but it checks in which :class:`AuiManager` rectangle the 4376 input point belongs to. 4377 4378 :param `panes`: a list of :class:`AuiPaneInfo` instances; 4379 :param Point `pt`: the mouse position. 4380 """ 4381 4382 for paneInfo in panes: 4383 if paneInfo.IsDocked() and paneInfo.IsShown() and paneInfo.rect.Contains(pt): 4384 return paneInfo 4385 4386 return NonePaneInfo
4387 4388 4389 # SetAGWFlags() and GetAGWFlags() allow the owner to set various 4390 # options which are global to AuiManager 4391
4392 - def SetAGWFlags(self, agwFlags):
4393 """ 4394 This method is used to specify :class:`AuiManager` 's settings flags. 4395 4396 :param integer `agwFlags`: specifies options which allow the frame management behavior 4397 to be modified. `agwFlags` can be one of the following style bits: 4398 4399 ==================================== ================================== 4400 Flag name Description 4401 ==================================== ================================== 4402 ``AUI_MGR_ALLOW_FLOATING`` Allow floating of panes 4403 ``AUI_MGR_ALLOW_ACTIVE_PANE`` If a pane becomes active, "highlight" it in the interface 4404 ``AUI_MGR_TRANSPARENT_DRAG`` If the platform supports it, set transparency on a floating pane while it is dragged by the user 4405 ``AUI_MGR_TRANSPARENT_HINT`` If the platform supports it, show a transparent hint window when the user is about to dock a floating pane 4406 ``AUI_MGR_VENETIAN_BLINDS_HINT`` Show a "venetian blind" effect when the user is about to dock a floating pane 4407 ``AUI_MGR_RECTANGLE_HINT`` Show a rectangle hint effect when the user is about to dock a floating pane 4408 ``AUI_MGR_HINT_FADE`` If the platform supports it, the hint window will fade in and out 4409 ``AUI_MGR_NO_VENETIAN_BLINDS_FADE`` Disables the "venetian blind" fade in and out 4410 ``AUI_MGR_LIVE_RESIZE`` Live resize when the user drag a sash 4411 ``AUI_MGR_ANIMATE_FRAMES`` Fade-out floating panes when they are closed (all platforms which support frames transparency) 4412 and show a moving rectangle when they are docked (Windows < Vista and GTK only) 4413 ``AUI_MGR_AERO_DOCKING_GUIDES`` Use the new Aero-style bitmaps as docking guides 4414 ``AUI_MGR_PREVIEW_MINIMIZED_PANES`` Slide in and out minimized panes to preview them 4415 ``AUI_MGR_WHIDBEY_DOCKING_GUIDES`` Use the new Whidbey-style bitmaps as docking guides 4416 ``AUI_MGR_SMOOTH_DOCKING`` Performs a "smooth" docking of panes (a la PyQT) 4417 ``AUI_MGR_USE_NATIVE_MINIFRAMES`` Use miniframes with native caption bar as floating panes instead or custom drawn caption bars (forced on wxMAC) 4418 ``AUI_MGR_AUTONB_NO_CAPTION`` Panes that merge into an automatic notebook will not have the pane caption visible 4419 ==================================== ================================== 4420 4421 .. note:: 4422 4423 If using the ``AUI_MGR_USE_NATIVE_MINIFRAMES``, double-clicking on a 4424 floating pane caption will not re-dock the pane, but simply maximize it (if 4425 :meth:`AuiPaneInfo.MaximizeButton` has been set to ``True``) or do nothing. 4426 4427 """ 4428 4429 self._agwFlags = agwFlags 4430 4431 if len(self._guides) > 0: 4432 self.CreateGuideWindows() 4433 4434 if self._hint_window and agwFlags & AUI_MGR_RECTANGLE_HINT == 0: 4435 self.CreateHintWindow()
4436 4437
4438 - def GetAGWFlags(self):
4439 """ 4440 Returns the current manager's flags. 4441 4442 :see: :meth:`SetAGWFlags` for a list of possible :class:`AuiManager` flags. 4443 """ 4444 4445 return self._agwFlags
4446 4447
4448 - def SetManagedWindow(self, managed_window):
4449 """ 4450 Called to specify the frame or window which is to be managed by :class:`AuiManager`. 4451 Frame management is not restricted to just frames. Child windows or custom 4452 controls are also allowed. 4453 4454 :param Window `managed_window`: specifies the window which should be managed by 4455 the AUI manager. 4456 """ 4457 4458 if not managed_window: 4459 raise Exception("Specified managed window must be non-null. ") 4460 4461 self.UnInit() 4462 4463 self._frame = managed_window 4464 self._frame.PushEventHandler(self) 4465 4466 # if the owner is going to manage an MDI parent frame, 4467 # we need to add the MDI client window as the default 4468 # center pane 4469 4470 if isinstance(self._frame, wx.MDIParentFrame): 4471 mdi_frame = self._frame 4472 client_window = mdi_frame.GetClientWindow() 4473 4474 if not client_window: 4475 raise Exception("Client window is None!") 4476 4477 self.AddPane(client_window, AuiPaneInfo().Name("mdiclient"). 4478 CenterPane().PaneBorder(False)) 4479 4480 elif isinstance(self._frame, tabmdi.AuiMDIParentFrame): 4481 4482 mdi_frame = self._frame 4483 client_window = mdi_frame.GetClientWindow() 4484 4485 if not client_window: 4486 raise Exception("Client window is None!") 4487 4488 self.AddPane(client_window, AuiPaneInfo().Name("mdiclient"). 4489 CenterPane().PaneBorder(False))
4490 4491
4492 - def GetManagedWindow(self):
4493 """ Returns the window being managed by :class:`AuiManager`. """ 4494 4495 return self._frame
4496 4497
4498 - def SetFrame(self, managed_window):
4499 """ 4500 Called to specify the frame or window which is to be managed by :class:`AuiManager`. 4501 Frame management is not restricted to just frames. Child windows or custom 4502 controls are also allowed. 4503 4504 :param Window `managed_window`: specifies the window which should be managed by 4505 the AUI manager. 4506 4507 .. deprecated:: 0.6 4508 This method is now deprecated, use :meth:`SetManagedWindow` instead. 4509 """ 4510 4511 DeprecationWarning("This method is deprecated, use SetManagedWindow instead.") 4512 return self.SetManagedWindow(managed_window)
4513 4514
4515 - def GetFrame(self):
4516 """ 4517 Returns the window being managed by :class:`AuiManager`. 4518 4519 .. deprecated:: 0.6 4520 This method is now deprecated, use :meth:`GetManagedWindow` instead. 4521 """ 4522 4523 DeprecationWarning("This method is deprecated, use GetManagedWindow instead.") 4524 return self._frame
4525 4526
4527 - def CreateGuideWindows(self):
4528 """ Creates the VS2005 HUD guide windows. """ 4529 4530 self.DestroyGuideWindows() 4531 4532 self._guides.append(AuiDockingGuideInfo().Left(). 4533 Host(AuiSingleDockingGuide(self._frame, wx.LEFT))) 4534 self._guides.append(AuiDockingGuideInfo().Top(). 4535 Host(AuiSingleDockingGuide(self._frame, wx.TOP))) 4536 self._guides.append(AuiDockingGuideInfo().Right(). 4537 Host(AuiSingleDockingGuide(self._frame, wx.RIGHT))) 4538 self._guides.append(AuiDockingGuideInfo().Bottom(). 4539 Host(AuiSingleDockingGuide(self._frame, wx.BOTTOM))) 4540 self._guides.append(AuiDockingGuideInfo().Centre(). 4541 Host(AuiCenterDockingGuide(self._frame)))
4542 4543
4544 - def DestroyGuideWindows(self):
4545 """ Destroys the VS2005 HUD guide windows. """ 4546 4547 for guide in self._guides: 4548 if guide.host: 4549 guide.host.Destroy() 4550 4551 self._guides = []
4552 4553
4554 - def CreateHintWindow(self):
4555 """ Creates the standard wxAUI hint window. """ 4556 4557 self.DestroyHintWindow() 4558 4559 self._hint_window = AuiDockingHintWindow(self._frame) 4560 self._hint_window.SetBlindMode(self._agwFlags)
4561 4562
4563 - def DestroyHintWindow(self):
4564 """ Destroys the standard wxAUI hint window. """ 4565 4566 if self._hint_window: 4567 4568 self._hint_window.Destroy() 4569 self._hint_window = None
4570 4571
4572 - def UnInit(self):
4573 """ 4574 Uninitializes the framework and should be called before a managed frame or 4575 window is destroyed. :meth:`UnInit` is usually called in the managed :class:`Frame` / :class:`Window` 4576 destructor. 4577 4578 It is necessary to call this function before the managed frame or window is 4579 destroyed, otherwise the manager cannot remove its custom event handlers 4580 from a window. 4581 """ 4582 4583 if not self._frame: 4584 return 4585 4586 for klass in [self._frame] + list(self._frame.GetChildren()): 4587 handler = klass.GetEventHandler() 4588 if klass is not handler: 4589 if isinstance(handler, AuiManager): 4590 klass.RemoveEventHandler(handler)
4591 4592
4593 - def OnDestroy(self, event) :
4594 4595 if self._frame == event.GetEventObject(): 4596 self.UnInit();
4597 4598
4599 - def GetArtProvider(self):
4600 """ Returns the current art provider being used. """ 4601 4602 return self._art
4603 4604
4605 - def ProcessMgrEvent(self, event):
4606 """ 4607 Process the AUI events sent to the manager. 4608 4609 :param `event`: the event to process, an instance of :class:`AuiManagerEvent`. 4610 """ 4611 4612 # first, give the owner frame a chance to override 4613 if self._frame: 4614 if self._frame.GetEventHandler().ProcessEvent(event): 4615 return 4616 4617 self.ProcessEvent(event)
4618 4619
4620 - def FireEvent(self, evtType, pane, canVeto=False):
4621 """ 4622 Fires one of the ``EVT_AUI_PANE_FLOATED`` / ``FLOATING`` / ``DOCKING`` / ``DOCKED`` / ``ACTIVATED`` event. 4623 4624 :param integer `evtType`: one of the aforementioned events; 4625 :param `pane`: the :class:`AuiPaneInfo` instance associated to this event; 4626 :param bool `canVeto`: whether the event can be vetoed or not. 4627 """ 4628 4629 event = AuiManagerEvent(evtType) 4630 event.SetPane(pane) 4631 event.SetCanVeto(canVeto) 4632 self.ProcessMgrEvent(event) 4633 4634 return event
4635 4636
4637 - def CanUseModernDockArt(self):
4638 """ 4639 Returns whether :class:`dockart` can be used (Windows XP / Vista / 7 only, 4640 requires Mark Hammonds's `pywin32 <http://sourceforge.net/projects/pywin32/>`_ package). 4641 """ 4642 4643 if not _winxptheme: 4644 return False 4645 4646 # Get the size of a small close button (themed) 4647 hwnd = self._frame.GetHandle() 4648 hTheme = winxptheme.OpenThemeData(hwnd, "Window") 4649 4650 if not hTheme: 4651 return False 4652 4653 return True
4654 4655
4656 - def SetArtProvider(self, art_provider):
4657 """ 4658 Instructs :class:`AuiManager` to use art provider specified by the parameter 4659 `art_provider` for all drawing calls. This allows plugable look-and-feel 4660 features. 4661 4662 :param `art_provider`: a AUI dock art provider. 4663 4664 :note: The previous art provider object, if any, will be deleted by :class:`AuiManager`. 4665 """ 4666 4667 # delete the last art provider, if any 4668 del self._art 4669 4670 # assign the new art provider 4671 self._art = art_provider 4672 4673 for pane in self.GetAllPanes(): 4674 if pane.IsFloating() and pane.frame: 4675 pane.frame._mgr.SetArtProvider(art_provider) 4676 pane.frame._mgr.Update()
4677 4678
4679 - def AddPane(self, window, arg1=None, arg2=None, target=None):
4680 """ 4681 Tells the frame manager to start managing a child window. There 4682 are four versions of this function. The first verison allows the full spectrum 4683 of pane parameter possibilities (:meth:`AddPane1`). The second version is used for 4684 simpler user interfaces which do not require as much configuration (:meth:`AddPane2`). 4685 The :meth:`AddPane3` version allows a drop position to be specified, which will determine 4686 where the pane will be added. The :meth:`AddPane4` version allows to turn the target 4687 :class:`AuiPaneInfo` pane into a notebook and the added pane into a page. 4688 4689 In your code, simply call :meth:`AddPane`. 4690 4691 :param Window `window`: the child window to manage; 4692 :param `arg1`: a :class:`AuiPaneInfo` or an integer value (direction); 4693 :param `arg2`: a :class:`AuiPaneInfo` or a :class:`Point` (drop position); 4694 :param `target`: a :class:`AuiPaneInfo` to be turned into a notebook 4695 and new pane added to it as a page. (additionally, target can be any pane in 4696 an existing notebook) 4697 """ 4698 4699 if target in self._panes: 4700 return self.AddPane4(window, arg1, target) 4701 4702 if type(arg1) == type(1): 4703 # This Is Addpane2 4704 if arg1 is None: 4705 arg1 = wx.LEFT 4706 if arg2 is None: 4707 arg2 = "" 4708 return self.AddPane2(window, arg1, arg2) 4709 else: 4710 if isinstance(arg2, wx.Point): 4711 return self.AddPane3(window, arg1, arg2) 4712 else: 4713 return self.AddPane1(window, arg1)
4714 4715
4716 - def AddPane1(self, window, pane_info):
4717 """ See comments on :meth:`AddPane`. """ 4718 4719 # check if the pane has a valid window 4720 if not window: 4721 return False 4722 4723 # check if the pane already exists 4724 if self.GetPane(pane_info.window).IsOk(): 4725 return False 4726 4727 # check if the pane name already exists, this could reveal a 4728 # bug in the library user's application 4729 already_exists = False 4730 if pane_info.name != "" and self.GetPane(pane_info.name).IsOk(): 4731 warnings.warn("A pane with the name '%s' already exists in the manager!"%pane_info.name) 4732 already_exists = True 4733 4734 # if the new pane is docked then we should undo maximize 4735 if pane_info.IsDocked(): 4736 self.RestoreMaximizedPane() 4737 4738 self._panes.append(pane_info) 4739 pinfo = self._panes[-1] 4740 4741 # set the pane window 4742 pinfo.window = window 4743 4744 # if the pane's name identifier is blank, create a random string 4745 if pinfo.name == "" or already_exists: 4746 pinfo.name = ("%s%08x%08x%08x")%(pinfo.window.GetName(), time.time(), 4747 time.clock(), len(self._panes)) 4748 4749 # set initial proportion (if not already set) 4750 if pinfo.dock_proportion == 0: 4751 pinfo.dock_proportion = 100000 4752 4753 floating = isinstance(self._frame, AuiFloatingFrame) 4754 4755 pinfo.buttons = [] 4756 4757 if not floating and pinfo.HasMinimizeButton(): 4758 button = AuiPaneButton(AUI_BUTTON_MINIMIZE) 4759 pinfo.buttons.append(button) 4760 4761 if not floating and pinfo.HasMaximizeButton(): 4762 button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE) 4763 pinfo.buttons.append(button) 4764 4765 if not floating and pinfo.HasPinButton(): 4766 button = AuiPaneButton(AUI_BUTTON_PIN) 4767 pinfo.buttons.append(button) 4768 4769 if pinfo.HasCloseButton(): 4770 button = AuiPaneButton(AUI_BUTTON_CLOSE) 4771 pinfo.buttons.append(button) 4772 4773 if pinfo.HasGripper(): 4774 if isinstance(pinfo.window, auibar.AuiToolBar): 4775 # prevent duplicate gripper -- both AuiManager and AuiToolBar 4776 # have a gripper control. The toolbar's built-in gripper 4777 # meshes better with the look and feel of the control than ours, 4778 # so turn AuiManager's gripper off, and the toolbar's on. 4779 4780 tb = pinfo.window 4781 pinfo.SetFlag(AuiPaneInfo.optionGripper, False) 4782 tb.SetGripperVisible(True) 4783 4784 if pinfo.window: 4785 if pinfo.best_size == wx.Size(-1, -1): 4786 pinfo.best_size = pinfo.window.GetClientSize() 4787 4788 if isinstance(pinfo.window, wx.ToolBar): 4789 # GetClientSize() doesn't get the best size for 4790 # a toolbar under some newer versions of wxWidgets, 4791 # so use GetBestSize() 4792 pinfo.best_size = pinfo.window.GetBestSize() 4793 4794 # this is needed for Win2000 to correctly fill toolbar backround 4795 # it should probably be repeated once system colour change happens 4796 if wx.Platform == "__WXMSW__" and pinfo.window.UseBgCol(): 4797 pinfo.window.SetBackgroundColour(self.GetArtProvider().GetColour(AUI_DOCKART_BACKGROUND_COLOUR)) 4798 4799 if pinfo.min_size != wx.Size(-1, -1): 4800 if pinfo.best_size.x < pinfo.min_size.x: 4801 pinfo.best_size.x = pinfo.min_size.x 4802 if pinfo.best_size.y < pinfo.min_size.y: 4803 pinfo.best_size.y = pinfo.min_size.y 4804 4805 self._panes[-1] = pinfo 4806 if isinstance(window, auibar.AuiToolBar): 4807 window.SetAuiManager(self) 4808 4809 return True
4810 4811
4812 - def AddPane2(self, window, direction, caption):
4813 """ See comments on :meth:`AddPane`. """ 4814 4815 pinfo = AuiPaneInfo() 4816 pinfo.Caption(caption) 4817 4818 if direction == wx.TOP: 4819 pinfo.Top() 4820 elif direction == wx.BOTTOM: 4821 pinfo.Bottom() 4822 elif direction == wx.LEFT: 4823 pinfo.Left() 4824 elif direction == wx.RIGHT: 4825 pinfo.Right() 4826 elif direction == wx.CENTER: 4827 pinfo.CenterPane() 4828 4829 return self.AddPane(window, pinfo)
4830 4831
4832 - def AddPane3(self, window, pane_info, drop_pos):
4833 """ See comments on :meth:`AddPane`. """ 4834 4835 if not self.AddPane(window, pane_info): 4836 return False 4837 4838 pane = self.GetPane(window) 4839 indx = self._panes.index(pane) 4840 4841 ret, pane = self.DoDrop(self._docks, self._panes, pane, drop_pos, wx.Point(0, 0)) 4842 self._panes[indx] = pane 4843 4844 return True
4845 4846
4847 - def AddPane4(self, window, pane_info, target):
4848 """ See comments on :meth:`AddPane`. """ 4849 4850 if not self.AddPane(window, pane_info): 4851 return False 4852 4853 paneInfo = self.GetPane(window) 4854 4855 if not paneInfo.IsNotebookDockable(): 4856 return self.AddPane1(window, pane_info) 4857 if not target.IsNotebookDockable() and not target.IsNotebookControl(): 4858 return self.AddPane1(window, pane_info) 4859 4860 if not target.HasNotebook(): 4861 self.CreateNotebookBase(self._panes, target) 4862 4863 # Add new item to notebook 4864 paneInfo.NotebookPage(target.notebook_id) 4865 4866 # we also want to remove our captions sometimes 4867 self.RemoveAutoNBCaption(paneInfo) 4868 self.UpdateNotebook() 4869 4870 return True
4871 4872
4873 - def InsertPane(self, window, pane_info, insert_level=AUI_INSERT_PANE):
4874 """ 4875 This method is used to insert either a previously unmanaged pane window 4876 into the frame manager, or to insert a currently managed pane somewhere else. 4877 :meth:`InsertPane` will push all panes, rows, or docks aside and insert the window 4878 into the position specified by `pane_info`. 4879 4880 Because `pane_info` can specify either a pane, dock row, or dock layer, the 4881 `insert_level` parameter is used to disambiguate this. The parameter `insert_level` 4882 can take a value of ``AUI_INSERT_PANE``, ``AUI_INSERT_ROW`` or ``AUI_INSERT_DOCK``. 4883 4884 :param Window `window`: the window to be inserted and managed; 4885 :param `pane_info`: the insert location for the new window; 4886 :param integer `insert_level`: the insertion level of the new pane. 4887 """ 4888 4889 if not window: 4890 raise Exception("Invalid window passed to InsertPane.") 4891 4892 # shift the panes around, depending on the insert level 4893 if insert_level == AUI_INSERT_PANE: 4894 self._panes = DoInsertPane(self._panes, pane_info.dock_direction, 4895 pane_info.dock_layer, pane_info.dock_row, 4896 pane_info.dock_pos) 4897 4898 elif insert_level == AUI_INSERT_ROW: 4899 self._panes = DoInsertDockRow(self._panes, pane_info.dock_direction, 4900 pane_info.dock_layer, pane_info.dock_row) 4901 4902 elif insert_level == AUI_INSERT_DOCK: 4903 self._panes = DoInsertDockLayer(self._panes, pane_info.dock_direction, 4904 pane_info.dock_layer) 4905 4906 # if the window already exists, we are basically just moving/inserting the 4907 # existing window. If it doesn't exist, we need to add it and insert it 4908 existing_pane = self.GetPane(window) 4909 indx = self._panes.index(existing_pane) 4910 4911 if not existing_pane.IsOk(): 4912 4913 return self.AddPane(window, pane_info) 4914 4915 else: 4916 4917 if pane_info.IsFloating(): 4918 existing_pane.Float() 4919 if pane_info.floating_pos != wx.Point(-1, -1): 4920 existing_pane.FloatingPosition(pane_info.floating_pos) 4921 if pane_info.floating_size != wx.Size(-1, -1): 4922 existing_pane.FloatingSize(pane_info.floating_size) 4923 else: 4924 # if the new pane is docked then we should undo maximize 4925 self.RestoreMaximizedPane() 4926 4927 existing_pane.Direction(pane_info.dock_direction) 4928 existing_pane.Layer(pane_info.dock_layer) 4929 existing_pane.Row(pane_info.dock_row) 4930 existing_pane.Position(pane_info.dock_pos) 4931 4932 self._panes[indx] = existing_pane 4933 4934 return True
4935 4936
4937 - def DetachPane(self, window):
4938 """ 4939 Tells the :class:`AuiManager` to stop managing the pane specified 4940 by `window`. The window, if in a floated frame, is reparented to the frame 4941 managed by :class:`AuiManager`. 4942 4943 :param Window `window`: the window to be un-managed. 4944 """ 4945 4946 for p in self._panes: 4947 if p.window == window: 4948 if p.frame: 4949 # we have a floating frame which is being detached. We need to 4950 # reparent it to self._frame and destroy the floating frame 4951 4952 # reduce flicker 4953 p.window.SetSize((1, 1)) 4954 if p.frame.IsShown(): 4955 p.frame.Show(False) 4956 4957 if self._action_window == p.frame: 4958 self._action_window = None 4959 4960 # reparent to self._frame and destroy the pane 4961 p.window.Reparent(self._frame) 4962 p.frame.SetSizer(None) 4963 p.frame.Destroy() 4964 p.frame = None 4965 4966 elif p.IsNotebookPage(): 4967 notebook = self._notebooks[p.notebook_id] 4968 id = notebook.GetPageIndex(p.window) 4969 notebook.RemovePage(id) 4970 4971 # make sure there are no references to this pane in our uiparts, 4972 # just in case the caller doesn't call Update() immediately after 4973 # the DetachPane() call. This prevets obscure crashes which would 4974 # happen at window repaint if the caller forgets to call Update() 4975 counter = 0 4976 for pi in xrange(len(self._uiparts)): 4977 part = self._uiparts[counter] 4978 if part.pane == p: 4979 self._uiparts.pop(counter) 4980 counter -= 1 4981 4982 counter += 1 4983 4984 self._panes.remove(p) 4985 return True 4986 4987 return False
4988 4989
4990 - def ClosePane(self, pane_info):
4991 """ 4992 Destroys or hides the pane depending on its flags. 4993 4994 :param `pane_info`: a :class:`AuiPaneInfo` instance. 4995 """ 4996 4997 # if we were maximized, restore 4998 if pane_info.IsMaximized(): 4999 self.RestorePane(pane_info) 5000 5001 if pane_info.frame: 5002 if self._agwFlags & AUI_MGR_ANIMATE_FRAMES: 5003 pane_info.frame.FadeOut() 5004 5005 # first, hide the window 5006 if pane_info.window and pane_info.window.IsShown(): 5007 pane_info.window.Show(False) 5008 5009 # make sure that we are the parent of this window 5010 if pane_info.window and pane_info.window.GetParent() != self._frame: 5011 pane_info.window.Reparent(self._frame) 5012 5013 # if we have a frame, destroy it 5014 if pane_info.frame: 5015 pane_info.frame.Destroy() 5016 pane_info.frame = None 5017 5018 elif pane_info.IsNotebookPage(): 5019 # if we are a notebook page, remove ourselves... 5020 # the code would index out of bounds 5021 # if the last page of a sub-notebook was closed 5022 # because the notebook would be deleted, before this 5023 # code is executed. 5024 # This code just prevents an out-of bounds error. 5025 if self._notebooks: 5026 nid = pane_info.notebook_id 5027 if nid >= 0 and nid < len(self._notebooks): 5028 notebook = self._notebooks[nid] 5029 page_idx = notebook.GetPageIndex(pane_info.window) 5030 if page_idx >= 0: 5031 notebook.RemovePage(page_idx) 5032 5033 # now we need to either destroy or hide the pane 5034 to_destroy = 0 5035 if pane_info.IsDestroyOnClose(): 5036 to_destroy = pane_info.window 5037 self.DetachPane(to_destroy) 5038 else: 5039 if isinstance(pane_info.window, auibar.AuiToolBar) and pane_info.IsFloating(): 5040 tb = pane_info.window 5041 if pane_info.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT]: 5042 tb.SetAGWWindowStyleFlag(tb.GetAGWWindowStyleFlag() | AUI_TB_VERTICAL) 5043 5044 pane_info.Dock().Hide() 5045 5046 if pane_info.IsNotebookControl(): 5047 5048 notebook = self._notebooks[pane_info.notebook_id] 5049 while notebook.GetPageCount(): 5050 window = notebook.GetPage(0) 5051 notebook.RemovePage(0) 5052 info = self.GetPane(window) 5053 if info.IsOk(): 5054 info.notebook_id = -1 5055 info.dock_direction = AUI_DOCK_NONE 5056 # Note: this could change our paneInfo reference ... 5057 self.ClosePane(info) 5058 5059 if to_destroy: 5060 to_destroy.Destroy()
5061 5062
5063 - def MaximizePane(self, pane_info, savesizes=True):
5064 """ 5065 Maximizes the input pane. 5066 5067 :param `pane_info`: a :class:`AuiPaneInfo` instance. 5068 :param bool `savesizes`: whether to save previous dock sizes. 5069 """ 5070 5071 if savesizes: 5072 self.SavePreviousDockSizes(pane_info) 5073 5074 for p in self._panes: 5075 5076 # save hidden state 5077 p.SetFlag(p.savedHiddenState, p.HasFlag(p.optionHidden)) 5078 5079 if not p.IsToolbar() and not p.IsFloating(): 5080 p.Restore() 5081 5082 # hide the pane, because only the newly 5083 # maximized pane should show 5084 p.Hide() 5085 5086 pane_info.previousDockPos = pane_info.dock_pos 5087 5088 # mark ourselves maximized 5089 pane_info.Maximize() 5090 pane_info.Show() 5091 self._has_maximized = True 5092 5093 # last, show the window 5094 if pane_info.window and not pane_info.window.IsShown(): 5095 pane_info.window.Show(True)
5096 5097
5098 - def SavePreviousDockSizes(self, pane_info):
5099 """ 5100 Stores the previous dock sizes, to be used in a "restore" action later. 5101 5102 :param `pane_info`: a :class:`AuiPaneInfo` instance. 5103 """ 5104 5105 for d in self._docks: 5106 if not d.toolbar: 5107 for p in d.panes: 5108 p.previousDockSize = d.size 5109 if pane_info is not p: 5110 p.SetFlag(p.needsRestore, True)
5111 5112
5113 - def RestorePane(self, pane_info):
5114 """ 5115 Restores the input pane from a previous maximized or minimized state. 5116 5117 :param `pane_info`: a :class:`AuiPaneInfo` instance. 5118 """ 5119 5120 # restore all the panes 5121 for p in self._panes: 5122 if not p.IsToolbar(): 5123 p.SetFlag(p.optionHidden, p.HasFlag(p.savedHiddenState)) 5124 5125 pane_info.SetFlag(pane_info.needsRestore, True) 5126 5127 # mark ourselves non-maximized 5128 pane_info.Restore() 5129 self._has_maximized = False 5130 self._has_minimized = False 5131 5132 # last, show the window 5133 if pane_info.window and not pane_info.window.IsShown(): 5134 pane_info.window.Show(True)
5135 5136
5137 - def RestoreMaximizedPane(self):
5138 """ Restores the current maximized pane (if any). """ 5139 5140 # restore all the panes 5141 for p in self._panes: 5142 if p.IsMaximized(): 5143 self.RestorePane(p) 5144 break
5145 5146
5147 - def ActivatePane(self, window):
5148 """ 5149 Activates the pane to which `window` is associated. 5150 5151 :param `window`: a :class:`Window` derived window. 5152 """ 5153 5154 if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE: 5155 while window: 5156 ret, self._panes = SetActivePane(self._panes, window) 5157 if ret: 5158 break 5159 5160 window = window.GetParent() 5161 5162 self.RefreshCaptions() 5163 self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, window, canVeto=False)
5164 5165
5166 - def CreateNotebook(self):
5167 """ 5168 Creates an automatic :class:`~lib.agw.aui.auibook.AuiNotebook` when a pane is docked on 5169 top of another pane. 5170 """ 5171 5172 notebook = auibook.AuiNotebook(self._frame, -1, wx.Point(0, 0), wx.Size(0, 0), agwStyle=self._autoNBStyle) 5173 5174 # This is so we can get the tab-drag event. 5175 notebook.GetAuiManager().SetMasterManager(self) 5176 notebook.SetArtProvider(self._autoNBTabArt.Clone()) 5177 self._notebooks.append(notebook) 5178 5179 return notebook
5180 5181
5182 - def SetAutoNotebookTabArt(self, art):
5183 """ 5184 Sets the default tab art provider for automatic notebooks. 5185 5186 :param `art`: a tab art provider. 5187 """ 5188 5189 for nb in self._notebooks: 5190 nb.SetArtProvider(art.Clone()) 5191 nb.Refresh() 5192 nb.Update() 5193 5194 self._autoNBTabArt = art
5195 5196
5197 - def GetAutoNotebookTabArt(self):
5198 """ Returns the default tab art provider for automatic notebooks. """ 5199 5200 return self._autoNBTabArt
5201 5202
5203 - def SetAutoNotebookStyle(self, agwStyle):
5204 """ 5205 Sets the default AGW-specific window style for automatic notebooks. 5206 5207 :param integer `agwStyle`: the underlying :class:`~lib.agw.aui.auibook.AuiNotebook` window style. 5208 This can be a combination of the following bits: 5209 5210 ==================================== ================================== 5211 Flag name Description 5212 ==================================== ================================== 5213 ``AUI_NB_TOP`` With this style, tabs are drawn along the top of the notebook 5214 ``AUI_NB_LEFT`` With this style, tabs are drawn along the left of the notebook. Not implemented yet. 5215 ``AUI_NB_RIGHT`` With this style, tabs are drawn along the right of the notebook. Not implemented yet. 5216 ``AUI_NB_BOTTOM`` With this style, tabs are drawn along the bottom of the notebook 5217 ``AUI_NB_TAB_SPLIT`` Allows the tab control to be split by dragging a tab 5218 ``AUI_NB_TAB_MOVE`` Allows a tab to be moved horizontally by dragging 5219 ``AUI_NB_TAB_EXTERNAL_MOVE`` Allows a tab to be moved to another tab control 5220 ``AUI_NB_TAB_FIXED_WIDTH`` With this style, all tabs have the same width 5221 ``AUI_NB_SCROLL_BUTTONS`` With this style, left and right scroll buttons are displayed 5222 ``AUI_NB_WINDOWLIST_BUTTON`` With this style, a drop-down list of windows is available 5223 ``AUI_NB_CLOSE_BUTTON`` With this style, a close button is available on the tab bar 5224 ``AUI_NB_CLOSE_ON_ACTIVE_TAB`` With this style, a close button is available on the active tab 5225 ``AUI_NB_CLOSE_ON_ALL_TABS`` With this style, a close button is available on all tabs 5226 ``AUI_NB_MIDDLE_CLICK_CLOSE`` Allows to close :class:`~lib.agw.aui.auibook.AuiNotebook` tabs by mouse middle button click 5227 ``AUI_NB_SUB_NOTEBOOK`` This style is used by :class:`AuiManager` to create automatic AuiNotebooks 5228 ``AUI_NB_HIDE_ON_SINGLE_TAB`` Hides the tab window if only one tab is present 5229 ``AUI_NB_SMART_TABS`` Use Smart Tabbing, like ``Alt`` + ``Tab`` on Windows 5230 ``AUI_NB_USE_IMAGES_DROPDOWN`` Uses images on dropdown window list menu instead of check items 5231 ``AUI_NB_CLOSE_ON_TAB_LEFT`` Draws the tab close button on the left instead of on the right (a la Camino browser) 5232 ``AUI_NB_TAB_FLOAT`` Allows the floating of single tabs. Known limitation: when the notebook is more or less 5233 full screen, tabs cannot be dragged far enough outside of the notebook to become floating pages 5234 ``AUI_NB_DRAW_DND_TAB`` Draws an image representation of a tab while dragging (on by default) 5235 ``AUI_NB_ORDER_BY_ACCESS`` Tab navigation order by last access time for the tabs 5236 ``AUI_NB_NO_TAB_FOCUS`` Don't draw tab focus rectangle 5237 ==================================== ================================== 5238 5239 """ 5240 5241 for nb in self._notebooks: 5242 nb.SetAGWWindowStyleFlag(agwStyle) 5243 nb.Refresh() 5244 nb.Update() 5245 5246 self._autoNBStyle = agwStyle
5247 5248
5249 - def GetAutoNotebookStyle(self):
5250 """ 5251 Returns the default AGW-specific window style for automatic notebooks. 5252 5253 :see: :meth:`SetAutoNotebookStyle` method for a list of possible styles. 5254 """ 5255 5256 return self._autoNBStyle
5257 5258
5259 - def SavePaneInfo(self, pane):
5260 """ 5261 This method is similar to :meth:`SavePerspective`, with the exception 5262 that it only saves information about a single pane. It is used in 5263 combination with :meth:`LoadPaneInfo`. 5264 5265 :param `pane`: a :class:`AuiPaneInfo` instance to save. 5266 """ 5267 5268 result = "name=" + EscapeDelimiters(pane.name) + ";" 5269 result += "caption=" + EscapeDelimiters(pane.caption) + ";" 5270 5271 result += "state=%u;"%pane.state 5272 result += "dir=%d;"%pane.dock_direction 5273 result += "layer=%d;"%pane.dock_layer 5274 result += "row=%d;"%pane.dock_row 5275 result += "pos=%d;"%pane.dock_pos 5276 result += "prop=%d;"%pane.dock_proportion 5277 result += "bestw=%d;"%pane.best_size.x 5278 result += "besth=%d;"%pane.best_size.y 5279 result += "minw=%d;"%pane.min_size.x 5280 result += "minh=%d;"%pane.min_size.y 5281 result += "maxw=%d;"%pane.max_size.x 5282 result += "maxh=%d;"%pane.max_size.y 5283 result += "floatx=%d;"%pane.floating_pos.x 5284 result += "floaty=%d;"%pane.floating_pos.y 5285 result += "floatw=%d;"%pane.floating_size.x 5286 result += "floath=%d;"%pane.floating_size.y 5287 result += "notebookid=%d;"%pane.notebook_id 5288 result += "transparent=%d"%pane.transparent 5289 5290 return result
5291 5292
5293 - def LoadPaneInfo(self, pane_part, pane):
5294 """ 5295 This method is similar to to :meth:`LoadPerspective`, with the exception that 5296 it only loads information about a single pane. It is used in combination 5297 with :meth:`SavePaneInfo`. 5298 5299 :param string `pane_part`: the string to analyze; 5300 :param `pane`: the :class:`AuiPaneInfo` structure in which to load `pane_part`. 5301 """ 5302 5303 # replace escaped characters so we can 5304 # split up the string easily 5305 pane_part = pane_part.replace("\\|", "\a") 5306 pane_part = pane_part.replace("\\;", "\b") 5307 5308 options = pane_part.split(";") 5309 for items in options: 5310 5311 val_name, value = items.split("=") 5312 val_name = val_name.strip() 5313 5314 if val_name == "name": 5315 pane.name = value 5316 elif val_name == "caption": 5317 pane.caption = value 5318 elif val_name == "state": 5319 pane.state = int(value) 5320 elif val_name == "dir": 5321 pane.dock_direction = int(value) 5322 elif val_name == "layer": 5323 pane.dock_layer = int(value) 5324 elif val_name == "row": 5325 pane.dock_row = int(value) 5326 elif val_name == "pos": 5327 pane.dock_pos = int(value) 5328 elif val_name == "prop": 5329 pane.dock_proportion = int(value) 5330 elif val_name == "bestw": 5331 pane.best_size.x = int(value) 5332 elif val_name == "besth": 5333 pane.best_size.y = int(value) 5334 pane.best_size = wx.Size(pane.best_size.x, pane.best_size.y) 5335 elif val_name == "minw": 5336 pane.min_size.x = int(value) 5337 elif val_name == "minh": 5338 pane.min_size.y = int(value) 5339 pane.min_size = wx.Size(pane.min_size.x, pane.min_size.y) 5340 elif val_name == "maxw": 5341 pane.max_size.x = int(value) 5342 elif val_name == "maxh": 5343 pane.max_size.y = int(value) 5344 pane.max_size = wx.Size(pane.max_size.x, pane.max_size.y) 5345 elif val_name == "floatx": 5346 pane.floating_pos.x = int(value) 5347 elif val_name == "floaty": 5348 pane.floating_pos.y = int(value) 5349 pane.floating_pos = wx.Point(pane.floating_pos.x, pane.floating_pos.y) 5350 elif val_name == "floatw": 5351 pane.floating_size.x = int(value) 5352 elif val_name == "floath": 5353 pane.floating_size.y = int(value) 5354 pane.floating_size = wx.Size(pane.floating_size.x, pane.floating_size.y) 5355 elif val_name == "notebookid": 5356 pane.notebook_id = int(value) 5357 elif val_name == "transparent": 5358 pane.transparent = int(value) 5359 else: 5360 raise Exception("Bad perspective string") 5361 5362 # replace escaped characters so we can 5363 # split up the string easily 5364 pane.name = pane.name.replace("\a", "|") 5365 pane.name = pane.name.replace("\b", ";") 5366 pane.caption = pane.caption.replace("\a", "|") 5367 pane.caption = pane.caption.replace("\b", ";") 5368 pane_part = pane_part.replace("\a", "|") 5369 pane_part = pane_part.replace("\b", ";") 5370 5371 return pane
5372 5373
5374 - def SavePerspective(self):
5375 """ 5376 Saves the entire user interface layout into an encoded string, which can then 5377 be stored by the application (probably using :class:`Config`). 5378 5379 When a perspective is restored using :meth:`LoadPerspective`, the entire user 5380 interface will return to the state it was when the perspective was saved. 5381 """ 5382 5383 result = "layout2|" 5384 5385 for pane in self._panes: 5386 result += self.SavePaneInfo(pane) + "|" 5387 5388 for dock in self._docks: 5389 result = result + ("dock_size(%d,%d,%d)=%d|")%(dock.dock_direction, 5390 dock.dock_layer, 5391 dock.dock_row, 5392 dock.size) 5393 return result
5394 5395
5396 - def LoadPerspective(self, layout, update=True, restorecaption=False):
5397 """ 5398 Loads a layout which was saved with :meth:`SavePerspective`. 5399 5400 If the `update` flag parameter is ``True``, :meth:`Update` will be 5401 automatically invoked, thus realizing the saved perspective on screen. 5402 5403 :param string `layout`: a string which contains a saved AUI layout; 5404 :param bool `update`: whether to update immediately the window or not; 5405 :param bool `restorecaption`: ``False``, restore from persist storage, 5406 otherwise use the caption defined in code. 5407 """ 5408 5409 input = layout 5410 5411 # check layout string version 5412 # 'layout1' = wxAUI 0.9.0 - wxAUI 0.9.2 5413 # 'layout2' = wxAUI 0.9.2 (wxWidgets 2.8) 5414 index = input.find("|") 5415 part = input[0:index].strip() 5416 input = input[index+1:] 5417 5418 if part != "layout2": 5419 return False 5420 5421 # mark all panes currently managed as docked and hidden 5422 saveCapt = {} # see restorecaption param 5423 for pane in self._panes: 5424 pane.Dock().Hide() 5425 saveCapt[pane.name] = pane.caption 5426 5427 # clear out the dock array; this will be reconstructed 5428 self._docks = [] 5429 5430 # replace escaped characters so we can 5431 # split up the string easily 5432 input = input.replace("\\|", "\a") 5433 input = input.replace("\\;", "\b") 5434 5435 while 1: 5436 5437 pane = AuiPaneInfo() 5438 index = input.find("|") 5439 pane_part = input[0:index].strip() 5440 input = input[index+1:] 5441 5442 # if the string is empty, we're done parsing 5443 if pane_part == "": 5444 break 5445 5446 if pane_part[0:9] == "dock_size": 5447 index = pane_part.find("=") 5448 val_name = pane_part[0:index] 5449 value = pane_part[index+1:] 5450 5451 index = val_name.find("(") 5452 piece = val_name[index+1:] 5453 index = piece.find(")") 5454 piece = piece[0:index] 5455 5456 vals = piece.split(",") 5457 dir = int(vals[0]) 5458 layer = int(vals[1]) 5459 row = int(vals[2]) 5460 size = int(value) 5461 5462 dock = AuiDockInfo() 5463 dock.dock_direction = dir 5464 dock.dock_layer = layer 5465 dock.dock_row = row 5466 dock.size = size 5467 self._docks.append(dock) 5468 5469 continue 5470 5471 # Undo our escaping as LoadPaneInfo needs to take an unescaped 5472 # name so it can be called by external callers 5473 pane_part = pane_part.replace("\a", "|") 5474 pane_part = pane_part.replace("\b", ";") 5475 5476 pane = self.LoadPaneInfo(pane_part, pane) 5477 5478 p = self.GetPane(pane.name) 5479 # restore pane caption from code 5480 if restorecaption: 5481 if pane.name in saveCapt: 5482 pane.Caption(saveCapt[pane.name]) 5483 5484 if not p.IsOk(): 5485 if pane.IsNotebookControl(): 5486 # notebook controls - auto add... 5487 self._panes.append(pane) 5488 indx = self._panes.index(pane) 5489 else: 5490 # the pane window couldn't be found 5491 # in the existing layout -- skip it 5492 continue 5493 5494 else: 5495 indx = self._panes.index(p) 5496 pane.window = p.window 5497 pane.frame = p.frame 5498 pane.buttons = p.buttons 5499 self._panes[indx] = pane 5500 5501 if isinstance(pane.window, auibar.AuiToolBar) and (pane.IsFloatable() or pane.IsDockable()): 5502 pane.window.SetGripperVisible(True) 5503 5504 for p in self._panes: 5505 if p.IsMinimized(): 5506 self.MinimizePane(p, False) 5507 5508 if update: 5509 self.Update() 5510 5511 return True
5512 5513
5514 - def GetPanePositionsAndSizes(self, dock):
5515 """ 5516 Returns all the panes positions and sizes in a dock. 5517 5518 :param `dock`: a :class:`AuiDockInfo` instance. 5519 """ 5520 5521 caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) 5522 pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) 5523 gripper_size = self._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE) 5524 5525 positions = [] 5526 sizes = [] 5527 5528 action_pane = -1 5529 pane_count = len(dock.panes) 5530 5531 # find the pane marked as our action pane 5532 for pane_i in xrange(pane_count): 5533 pane = dock.panes[pane_i] 5534 if pane.HasFlag(AuiPaneInfo.actionPane): 5535 if action_pane != -1: 5536 raise Exception("Too many action panes!") 5537 action_pane = pane_i 5538 5539 # set up each panes default position, and 5540 # determine the size (width or height, depending 5541 # on the dock's orientation) of each pane 5542 for pane in dock.panes: 5543 positions.append(pane.dock_pos) 5544 size = 0 5545 5546 if pane.HasBorder(): 5547 size += pane_border_size*2 5548 5549 if dock.IsHorizontal(): 5550 if pane.HasGripper() and not pane.HasGripperTop(): 5551 size += gripper_size 5552 5553 if pane.HasCaptionLeft(): 5554 size += caption_size 5555 5556 size += pane.best_size.x 5557 5558 else: 5559 if pane.HasGripper() and pane.HasGripperTop(): 5560 size += gripper_size 5561 5562 if pane.HasCaption() and not pane.HasCaptionLeft(): 5563 size += caption_size 5564 5565 size += pane.best_size.y 5566 5567 sizes.append(size) 5568 5569 # if there is no action pane, just return the default 5570 # positions (as specified in pane.pane_pos) 5571 if action_pane == -1: 5572 return positions, sizes 5573 5574 offset = 0 5575 for pane_i in xrange(action_pane-1, -1, -1): 5576 amount = positions[pane_i+1] - (positions[pane_i] + sizes[pane_i]) 5577 if amount >= 0: 5578 offset += amount 5579 else: 5580 positions[pane_i] -= -amount 5581 5582 offset += sizes[pane_i] 5583 5584 # if the dock mode is fixed, make sure none of the panes 5585 # overlap we will bump panes that overlap 5586 offset = 0 5587 for pane_i in xrange(action_pane, pane_count): 5588 amount = positions[pane_i] - offset 5589 if amount >= 0: 5590 offset += amount 5591 else: 5592 positions[pane_i] += -amount 5593 5594 offset += sizes[pane_i] 5595 5596 return positions, sizes
5597 5598
5599 - def LayoutAddPane(self, cont, dock, pane, uiparts, spacer_only):
5600 """ 5601 Adds a pane into the existing layout (in an existing dock). 5602 5603 :param `cont`: a :class:`Sizer` object; 5604 :param `dock`: the :class:`AuiDockInfo` structure in which to add the pane; 5605 :param `pane`: the :class:`AuiPaneInfo` instance to add to the dock; 5606 :param `uiparts`: a list of UI parts in the interface; 5607 :param bool `spacer_only`: whether to add a simple spacer or a real window. 5608 """ 5609 5610 sizer_item = wx.SizerItem() 5611 caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) 5612 gripper_size = self._art.GetMetric(AUI_DOCKART_GRIPPER_SIZE) 5613 pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) 5614 pane_button_size = self._art.GetMetric(AUI_DOCKART_PANE_BUTTON_SIZE) 5615 5616 # find out the orientation of the item (orientation for panes 5617 # is the same as the dock's orientation) 5618 5619 if dock.IsHorizontal(): 5620 orientation = wx.HORIZONTAL 5621 else: 5622 orientation = wx.VERTICAL 5623 5624 # this variable will store the proportion 5625 # value that the pane will receive 5626 pane_proportion = pane.dock_proportion 5627 5628 horz_pane_sizer = wx.BoxSizer(wx.HORIZONTAL) 5629 vert_pane_sizer = wx.BoxSizer(wx.VERTICAL) 5630 5631 if pane.HasGripper(): 5632 5633 part = AuiDockUIPart() 5634 if pane.HasGripperTop(): 5635 sizer_item = vert_pane_sizer.Add((1, gripper_size), 0, wx.EXPAND) 5636 else: 5637 sizer_item = horz_pane_sizer.Add((gripper_size, 1), 0, wx.EXPAND) 5638 5639 part.type = AuiDockUIPart.typeGripper 5640 part.dock = dock 5641 part.pane = pane 5642 part.button = None 5643 part.orientation = orientation 5644 part.cont_sizer = horz_pane_sizer 5645 part.sizer_item = sizer_item 5646 uiparts.append(part) 5647 5648 button_count = len(pane.buttons) 5649 button_width_total = button_count*pane_button_size 5650 if button_count >= 1: 5651 button_width_total += 3 5652 5653 caption, captionLeft = pane.HasCaption(), pane.HasCaptionLeft() 5654 button_count = len(pane.buttons) 5655 5656 if captionLeft: 5657 caption_sizer = wx.BoxSizer(wx.VERTICAL) 5658 5659 # add pane buttons to the caption 5660 dummy_parts = [] 5661 for btn_id in xrange(len(pane.buttons)-1, -1, -1): 5662 sizer_item = caption_sizer.Add((caption_size, pane_button_size), 0, wx.EXPAND) 5663 part = AuiDockUIPart() 5664 part.type = AuiDockUIPart.typePaneButton 5665 part.dock = dock 5666 part.pane = pane 5667 part.button = pane.buttons[btn_id] 5668 part.orientation = orientation 5669 part.cont_sizer = caption_sizer 5670 part.sizer_item = sizer_item 5671 dummy_parts.append(part) 5672 5673 sizer_item = caption_sizer.Add((caption_size, 1), 1, wx.EXPAND) 5674 vert_pane_sizer = wx.BoxSizer(wx.HORIZONTAL) 5675 5676 # create the caption sizer 5677 part = AuiDockUIPart() 5678 5679 part.type = AuiDockUIPart.typeCaption 5680 part.dock = dock 5681 part.pane = pane 5682 part.button = None 5683 part.orientation = orientation 5684 part.cont_sizer = vert_pane_sizer 5685 part.sizer_item = sizer_item 5686 caption_part_idx = len(uiparts) 5687 uiparts.append(part) 5688 uiparts.extend(dummy_parts) 5689 5690 elif caption: 5691 5692 caption_sizer = wx.BoxSizer(wx.HORIZONTAL) 5693 sizer_item = caption_sizer.Add((1, caption_size), 1, wx.EXPAND) 5694 5695 # create the caption sizer 5696 part = AuiDockUIPart() 5697 5698 part.type = AuiDockUIPart.typeCaption 5699 part.dock = dock 5700 part.pane = pane 5701 part.button = None 5702 part.orientation = orientation 5703 part.cont_sizer = vert_pane_sizer 5704 part.sizer_item = sizer_item 5705 caption_part_idx = len(uiparts) 5706 uiparts.append(part) 5707 5708 # add pane buttons to the caption 5709 for button in pane.buttons: 5710 sizer_item = caption_sizer.Add((pane_button_size, caption_size), 0, wx.EXPAND) 5711 part = AuiDockUIPart() 5712 part.type = AuiDockUIPart.typePaneButton 5713 part.dock = dock 5714 part.pane = pane 5715 part.button = button 5716 part.orientation = orientation 5717 part.cont_sizer = caption_sizer 5718 part.sizer_item = sizer_item 5719 uiparts.append(part) 5720 5721 if caption or captionLeft: 5722 # if we have buttons, add a little space to the right 5723 # of them to ease visual crowding 5724 if button_count >= 1: 5725 if captionLeft: 5726 caption_sizer.Add((caption_size, 3), 0, wx.EXPAND) 5727 else: 5728 caption_sizer.Add((3, caption_size), 0, wx.EXPAND) 5729 5730 # add the caption sizer 5731 sizer_item = vert_pane_sizer.Add(caption_sizer, 0, wx.EXPAND) 5732 uiparts[caption_part_idx].sizer_item = sizer_item 5733 5734 # add the pane window itself 5735 if spacer_only or not pane.window: 5736 sizer_item = vert_pane_sizer.Add((1, 1), 1, wx.EXPAND) 5737 else: 5738 sizer_item = vert_pane_sizer.Add(pane.window, 1, wx.EXPAND) 5739 vert_pane_sizer.SetItemMinSize(pane.window, (1, 1)) 5740 5741 part = AuiDockUIPart() 5742 part.type = AuiDockUIPart.typePane 5743 part.dock = dock 5744 part.pane = pane 5745 part.button = None 5746 part.orientation = orientation 5747 part.cont_sizer = vert_pane_sizer 5748 part.sizer_item = sizer_item 5749 uiparts.append(part) 5750 5751 # determine if the pane should have a minimum size if the pane is 5752 # non-resizable (fixed) then we must set a minimum size. Alternatively, 5753 # if the pane.min_size is set, we must use that value as well 5754 5755 min_size = pane.min_size 5756 if pane.IsFixed(): 5757 if min_size == wx.Size(-1, -1): 5758 min_size = pane.best_size 5759 pane_proportion = 0 5760 5761 if min_size != wx.Size(-1, -1): 5762 vert_pane_sizer.SetItemMinSize(len(vert_pane_sizer.GetChildren())-1, (min_size.x, min_size.y)) 5763 5764 # add the vertical/horizontal sizer (caption, pane window) to the 5765 # horizontal sizer (gripper, vertical sizer) 5766 horz_pane_sizer.Add(vert_pane_sizer, 1, wx.EXPAND) 5767 5768 # finally, add the pane sizer to the dock sizer 5769 if pane.HasBorder(): 5770 # allowing space for the pane's border 5771 sizer_item = cont.Add(horz_pane_sizer, pane_proportion, 5772 wx.EXPAND | wx.ALL, pane_border_size) 5773 part = AuiDockUIPart() 5774 part.type = AuiDockUIPart.typePaneBorder 5775 part.dock = dock 5776 part.pane = pane 5777 part.button = None 5778 part.orientation = orientation 5779 part.cont_sizer = cont 5780 part.sizer_item = sizer_item 5781 uiparts.append(part) 5782 else: 5783 sizer_item = cont.Add(horz_pane_sizer, pane_proportion, wx.EXPAND) 5784 5785 return uiparts
5786 5787
5788 - def LayoutAddDock(self, cont, dock, uiparts, spacer_only):
5789 """ 5790 Adds a dock into the existing layout. 5791 5792 :param `cont`: a :class:`Sizer` object; 5793 :param `dock`: the :class:`AuiDockInfo` structure to add to the layout; 5794 :param `uiparts`: a list of UI parts in the interface; 5795 :param bool `spacer_only`: whether to add a simple spacer or a real window. 5796 """ 5797 5798 sizer_item = wx.SizerItem() 5799 part = AuiDockUIPart() 5800 5801 sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) 5802 orientation = (dock.IsHorizontal() and [wx.HORIZONTAL] or [wx.VERTICAL])[0] 5803 5804 # resizable bottom and right docks have a sash before them 5805 if not self._has_maximized and not dock.fixed and \ 5806 dock.dock_direction in [AUI_DOCK_BOTTOM, AUI_DOCK_RIGHT]: 5807 5808 sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND) 5809 5810 part.type = AuiDockUIPart.typeDockSizer 5811 part.orientation = orientation 5812 part.dock = dock 5813 part.pane = None 5814 part.button = None 5815 part.cont_sizer = cont 5816 part.sizer_item = sizer_item 5817 uiparts.append(part) 5818 5819 # create the sizer for the dock 5820 dock_sizer = wx.BoxSizer(orientation) 5821 5822 # add each pane to the dock 5823 has_maximized_pane = False 5824 pane_count = len(dock.panes) 5825 5826 if dock.fixed: 5827 5828 # figure out the real pane positions we will 5829 # use, without modifying the each pane's pane_pos member 5830 pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock) 5831 5832 offset = 0 5833 for pane_i in xrange(pane_count): 5834 5835 pane = dock.panes[pane_i] 5836 pane_pos = pane_positions[pane_i] 5837 5838 if pane.IsMaximized(): 5839 has_maximized_pane = True 5840 5841 amount = pane_pos - offset 5842 if amount > 0: 5843 5844 if dock.IsVertical(): 5845 sizer_item = dock_sizer.Add((1, amount), 0, wx.EXPAND) 5846 else: 5847 sizer_item = dock_sizer.Add((amount, 1), 0, wx.EXPAND) 5848 5849 part = AuiDockUIPart() 5850 part.type = AuiDockUIPart.typeBackground 5851 part.dock = dock 5852 part.pane = None 5853 part.button = None 5854 part.orientation = (orientation==wx.HORIZONTAL and \ 5855 [wx.VERTICAL] or [wx.HORIZONTAL])[0] 5856 part.cont_sizer = dock_sizer 5857 part.sizer_item = sizer_item 5858 uiparts.append(part) 5859 5860 offset = offset + amount 5861 5862 uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only) 5863 5864 offset = offset + pane_sizes[pane_i] 5865 5866 # at the end add a very small stretchable background area 5867 sizer_item = dock_sizer.Add((0, 0), 1, wx.EXPAND) 5868 part = AuiDockUIPart() 5869 part.type = AuiDockUIPart.typeBackground 5870 part.dock = dock 5871 part.pane = None 5872 part.button = None 5873 part.orientation = orientation 5874 part.cont_sizer = dock_sizer 5875 part.sizer_item = sizer_item 5876 uiparts.append(part) 5877 5878 else: 5879 5880 for pane_i in xrange(pane_count): 5881 5882 pane = dock.panes[pane_i] 5883 5884 if pane.IsMaximized(): 5885 has_maximized_pane = True 5886 5887 # if this is not the first pane being added, 5888 # we need to add a pane sizer 5889 if not self._has_maximized and pane_i > 0: 5890 sizer_item = dock_sizer.Add((sash_size, sash_size), 0, wx.EXPAND) 5891 part = AuiDockUIPart() 5892 part.type = AuiDockUIPart.typePaneSizer 5893 part.dock = dock 5894 part.pane = dock.panes[pane_i-1] 5895 part.button = None 5896 part.orientation = (orientation==wx.HORIZONTAL and \ 5897 [wx.VERTICAL] or [wx.HORIZONTAL])[0] 5898 part.cont_sizer = dock_sizer 5899 part.sizer_item = sizer_item 5900 uiparts.append(part) 5901 5902 uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only) 5903 5904 if dock.dock_direction == AUI_DOCK_CENTER or has_maximized_pane: 5905 sizer_item = cont.Add(dock_sizer, 1, wx.EXPAND) 5906 else: 5907 sizer_item = cont.Add(dock_sizer, 0, wx.EXPAND) 5908 5909 part = AuiDockUIPart() 5910 part.type = AuiDockUIPart.typeDock 5911 part.dock = dock 5912 part.pane = None 5913 part.button = None 5914 part.orientation = orientation 5915 part.cont_sizer = cont 5916 part.sizer_item = sizer_item 5917 uiparts.append(part) 5918 5919 if dock.IsHorizontal(): 5920 cont.SetItemMinSize(dock_sizer, (0, dock.size)) 5921 else: 5922 cont.SetItemMinSize(dock_sizer, (dock.size, 0)) 5923 5924 # top and left docks have a sash after them 5925 if not self._has_maximized and not dock.fixed and \ 5926 dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]: 5927 5928 sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND) 5929 5930 part = AuiDockUIPart() 5931 part.type = AuiDockUIPart.typeDockSizer 5932 part.dock = dock 5933 part.pane = None 5934 part.button = None 5935 part.orientation = orientation 5936 part.cont_sizer = cont 5937 part.sizer_item = sizer_item 5938 uiparts.append(part) 5939 5940 return uiparts
5941 5942
5943 - def LayoutAll(self, panes, docks, uiparts, spacer_only=False, oncheck=True):
5944 """ 5945 Layouts all the UI structures in the interface. 5946 5947 :param `panes`: a list of :class:`AuiPaneInfo` instances; 5948 :param `docks`: a list of :class:`AuiDockInfo` classes; 5949 :param `uiparts`: a list of UI parts in the interface; 5950 :param bool `spacer_only`: whether to add a simple spacer or a real window; 5951 :param bool `oncheck`: whether to store the results in a class member or not. 5952 """ 5953 5954 container = wx.BoxSizer(wx.VERTICAL) 5955 5956 pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) 5957 caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) 5958 cli_size = self._frame.GetClientSize() 5959 5960 # empty all docks out 5961 for dock in docks: 5962 dock.panes = [] 5963 if dock.fixed: 5964 # always reset fixed docks' sizes, because 5965 # the contained windows may have been resized 5966 dock.size = 0 5967 5968 dock_count = len(docks) 5969 5970 # iterate through all known panes, filing each 5971 # of them into the appropriate dock. If the 5972 # pane does not exist in the dock, add it 5973 for p in panes: 5974 5975 # don't layout hidden panes. 5976 if p.IsShown(): 5977 5978 # find any docks with the same dock direction, dock layer, and 5979 # dock row as the pane we are working on 5980 arr = FindDocks(docks, p.dock_direction, p.dock_layer, p.dock_row) 5981 5982 if arr: 5983 dock = arr[0] 5984 5985 else: 5986 # dock was not found, so we need to create a new one 5987 d = AuiDockInfo() 5988 d.dock_direction = p.dock_direction 5989 d.dock_layer = p.dock_layer 5990 d.dock_row = p.dock_row 5991 docks.append(d) 5992 dock = docks[-1] 5993 5994 if p.HasFlag(p.needsRestore) and not p.HasFlag(p.wasMaximized): 5995 5996 isHor = dock.IsHorizontal() 5997 sashSize = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) 5998 5999 # get the sizes of any docks that might 6000 # overlap with our restored dock 6001 6002 # make list of widths or heights from the size in the dock rects 6003 sizes = [d.rect[2:][isHor] for \ 6004 d in docks if d.IsOk() and \ 6005 (d.IsHorizontal() == isHor) and \ 6006 not d.toolbar and \ 6007 d.dock_direction != AUI_DOCK_CENTER] 6008 6009 frameRect = GetInternalFrameRect(self._frame, self._docks) 6010 6011 # set max size allowing for sashes and absolute minimum 6012 maxsize = frameRect[2:][isHor] - sum(sizes) - (len(sizes)*10) - (sashSize*len(sizes)) 6013 dock.size = min(p.previousDockSize,maxsize) 6014 6015 else: 6016 dock.size = 0 6017 6018 if p.HasFlag(p.wasMaximized): 6019 self.MaximizePane(p, savesizes=False) 6020 p.SetFlag(p.wasMaximized, False) 6021 6022 if p.HasFlag(p.needsRestore): 6023 if p.previousDockPos is not None: 6024 DoInsertPane(dock.panes, dock.dock_direction, dock.dock_layer, dock.dock_row, p.previousDockPos) 6025 p.dock_pos = p.previousDockPos 6026 p.previousDockPos = None 6027 p.SetFlag(p.needsRestore, False) 6028 6029 if p.IsDocked(): 6030 # remove the pane from any existing docks except this one 6031 docks = RemovePaneFromDocks(docks, p, dock) 6032 6033 # pane needs to be added to the dock, 6034 # if it doesn't already exist 6035 if not FindPaneInDock(dock, p.window): 6036 dock.panes.append(p) 6037 else: 6038 # remove the pane from any existing docks 6039 docks = RemovePaneFromDocks(docks, p) 6040 6041 # remove any empty docks 6042 docks = [dock for dock in docks if dock.panes] 6043 6044 dock_count = len(docks) 6045 # configure the docks further 6046 for ii, dock in enumerate(docks): 6047 # sort the dock pane array by the pane's 6048 # dock position (dock_pos), in ascending order 6049 dock.panes.sort(PaneSortFunc) 6050 dock_pane_count = len(dock.panes) 6051 6052 # for newly created docks, set up their initial size 6053 if dock.size == 0: 6054 size = 0 6055 for pane in dock.panes: 6056 pane_size = pane.best_size 6057 if pane_size == wx.Size(-1, -1): 6058 pane_size = pane.min_size 6059 if pane_size == wx.Size(-1, -1) and pane.window: 6060 pane_size = pane.window.GetSize() 6061 if dock.IsHorizontal(): 6062 size = max(pane_size.y, size) 6063 else: 6064 size = max(pane_size.x, size) 6065 6066 # add space for the border (two times), but only 6067 # if at least one pane inside the dock has a pane border 6068 for pane in dock.panes: 6069 if pane.HasBorder(): 6070 size = size + pane_border_size*2 6071 break 6072 6073 # if pane is on the top or bottom, add the caption height, 6074 # but only if at least one pane inside the dock has a caption 6075 if dock.IsHorizontal(): 6076 for pane in dock.panes: 6077 if pane.HasCaption() and not pane.HasCaptionLeft(): 6078 size = size + caption_size 6079 break 6080 else: 6081 for pane in dock.panes: 6082 if pane.HasCaptionLeft() and not pane.HasCaption(): 6083 size = size + caption_size 6084 break 6085 6086 # new dock's size may not be more than the dock constraint 6087 # parameter specifies. See SetDockSizeConstraint() 6088 max_dock_x_size = int(self._dock_constraint_x*float(cli_size.x)) 6089 max_dock_y_size = int(self._dock_constraint_y*float(cli_size.y)) 6090 if cli_size <= wx.Size(20, 20): 6091 max_dock_x_size = 10000 6092 max_dock_y_size = 10000 6093 6094 if dock.IsHorizontal(): 6095 size = min(size, max_dock_y_size) 6096 else: 6097 size = min(size, max_dock_x_size) 6098 6099 # absolute minimum size for a dock is 10 pixels 6100 if size < 10: 6101 size = 10 6102 6103 dock.size = size 6104 6105 # determine the dock's minimum size 6106 plus_border = False 6107 plus_caption = False 6108 plus_caption_left = False 6109 dock_min_size = 0 6110 for pane in dock.panes: 6111 if pane.min_size != wx.Size(-1, -1): 6112 if pane.HasBorder(): 6113 plus_border = True 6114 if pane.HasCaption(): 6115 plus_caption = True 6116 if pane.HasCaptionLeft(): 6117 plus_caption_left = True 6118 if dock.IsHorizontal(): 6119 if pane.min_size.y > dock_min_size: 6120 dock_min_size = pane.min_size.y 6121 else: 6122 if pane.min_size.x > dock_min_size: 6123 dock_min_size = pane.min_size.x 6124 6125 if plus_border: 6126 dock_min_size += pane_border_size*2 6127 if plus_caption and dock.IsHorizontal(): 6128 dock_min_size += caption_size 6129 if plus_caption_left and dock.IsVertical(): 6130 dock_min_size += caption_size 6131 6132 dock.min_size = dock_min_size 6133 6134 # if the pane's current size is less than it's 6135 # minimum, increase the dock's size to it's minimum 6136 if dock.size < dock.min_size: 6137 dock.size = dock.min_size 6138 6139 # determine the dock's mode (fixed or proportional) 6140 # determine whether the dock has only toolbars 6141 action_pane_marked = False 6142 dock.fixed = True 6143 dock.toolbar = True 6144 for pane in dock.panes: 6145 if not pane.IsFixed(): 6146 dock.fixed = False 6147 if not pane.IsToolbar(): 6148 dock.toolbar = False 6149 if pane.HasFlag(AuiPaneInfo.optionDockFixed): 6150 dock.fixed = True 6151 if pane.HasFlag(AuiPaneInfo.actionPane): 6152 action_pane_marked = True 6153 6154 # if the dock mode is proportional and not fixed-pixel, 6155 # reassign the dock_pos to the sequential 0, 1, 2, 3 6156 # e.g. remove gaps like 1, 2, 30, 500 6157 if not dock.fixed: 6158 for jj in xrange(dock_pane_count): 6159 pane = dock.panes[jj] 6160 pane.dock_pos = jj 6161 6162 # if the dock mode is fixed, and none of the panes 6163 # are being moved right now, make sure the panes 6164 # do not overlap each other. If they do, we will 6165 # adjust the panes' positions 6166 if dock.fixed and not action_pane_marked: 6167 pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock) 6168 offset = 0 6169 for jj in xrange(dock_pane_count): 6170 pane = dock.panes[jj] 6171 pane.dock_pos = pane_positions[jj] 6172 amount = pane.dock_pos - offset 6173 if amount >= 0: 6174 offset += amount 6175 else: 6176 pane.dock_pos += -amount 6177 6178 offset += pane_sizes[jj] 6179 dock.panes[jj] = pane 6180 6181 if oncheck: 6182 self._docks[ii] = dock 6183 6184 # shrink docks if needed 6185 ## docks = self.SmartShrink(docks, AUI_DOCK_TOP) 6186 ## docks = self.SmartShrink(docks, AUI_DOCK_LEFT) 6187 6188 if oncheck: 6189 self._docks = docks 6190 6191 # discover the maximum dock layer 6192 max_layer = 0 6193 dock_count = len(docks) 6194 6195 for ii in xrange(dock_count): 6196 max_layer = max(max_layer, docks[ii].dock_layer) 6197 6198 # clear out uiparts 6199 uiparts = [] 6200 6201 # create a bunch of box sizers, 6202 # from the innermost level outwards. 6203 cont = None 6204 middle = None 6205 6206 if oncheck: 6207 docks = self._docks 6208 6209 for layer in xrange(max_layer+1): 6210 # find any docks in this layer 6211 arr = FindDocks(docks, -1, layer, -1) 6212 # if there aren't any, skip to the next layer 6213 if not arr: 6214 continue 6215 6216 old_cont = cont 6217 6218 # create a container which will hold this layer's 6219 # docks (top, bottom, left, right) 6220 cont = wx.BoxSizer(wx.VERTICAL) 6221 6222 # find any top docks in this layer 6223 arr = FindDocks(docks, AUI_DOCK_TOP, layer, -1) 6224 for row in arr: 6225 uiparts = self.LayoutAddDock(cont, row, uiparts, spacer_only) 6226 6227 # fill out the middle layer (which consists 6228 # of left docks, content area and right docks) 6229 6230 middle = wx.BoxSizer(wx.HORIZONTAL) 6231 6232 # find any left docks in this layer 6233 arr = FindDocks(docks, AUI_DOCK_LEFT, layer, -1) 6234 for row in arr: 6235 uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only) 6236 6237 # add content dock (or previous layer's sizer 6238 # to the middle 6239 if not old_cont: 6240 # find any center docks 6241 arr = FindDocks(docks, AUI_DOCK_CENTER, -1, -1) 6242 if arr: 6243 for row in arr: 6244 uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only) 6245 6246 elif not self._has_maximized: 6247 # there are no center docks, add a background area 6248 sizer_item = middle.Add((1, 1), 1, wx.EXPAND) 6249 part = AuiDockUIPart() 6250 part.type = AuiDockUIPart.typeBackground 6251 part.pane = None 6252 part.dock = None 6253 part.button = None 6254 part.cont_sizer = middle 6255 part.sizer_item = sizer_item 6256 uiparts.append(part) 6257 else: 6258 middle.Add(old_cont, 1, wx.EXPAND) 6259 6260 # find any right docks in this layer 6261 arr = FindDocks(docks, AUI_DOCK_RIGHT, layer, -1, reverse=True) 6262 for row in arr: 6263 uiparts = self.LayoutAddDock(middle, row, uiparts, spacer_only) 6264 6265 if len(middle.GetChildren()) > 0: 6266 cont.Add(middle, 1, wx.EXPAND) 6267 6268 # find any bottom docks in this layer 6269 arr = FindDocks(docks, AUI_DOCK_BOTTOM, layer, -1, reverse=True) 6270 for row in arr: 6271 uiparts = self.LayoutAddDock(cont, row, uiparts, spacer_only) 6272 6273 if not cont: 6274 # no sizer available, because there are no docks, 6275 # therefore we will create a simple background area 6276 cont = wx.BoxSizer(wx.VERTICAL) 6277 sizer_item = cont.Add((1, 1), 1, wx.EXPAND) 6278 part = AuiDockUIPart() 6279 part.type = AuiDockUIPart.typeBackground 6280 part.pane = None 6281 part.dock = None 6282 part.button = None 6283 part.cont_sizer = middle 6284 part.sizer_item = sizer_item 6285 uiparts.append(part) 6286 6287 if oncheck: 6288 self._uiparts = uiparts 6289 self._docks = docks 6290 6291 container.Add(cont, 1, wx.EXPAND) 6292 6293 if oncheck: 6294 return container 6295 else: 6296 return container, panes, docks, uiparts
6297 6298
6299 - def SetDockSizeConstraint(self, width_pct, height_pct):
6300 """ 6301 When a user creates a new dock by dragging a window into a docked position, 6302 often times the large size of the window will create a dock that is unwieldly 6303 large. 6304 6305 :class:`AuiManager` by default limits the size of any new dock to 1/3 of the window 6306 size. For horizontal docks, this would be 1/3 of the window height. For vertical 6307 docks, 1/3 of the width. Calling this function will adjust this constraint value. 6308 6309 The numbers must be between 0.0 and 1.0. For instance, calling :meth:`SetDockSizeConstraint` 6310 with (0.5, 0.5) will cause new docks to be limited to half of the size of the entire 6311 managed window. 6312 6313 :param float `width_pct`: a number representing the `x` dock size constraint; 6314 :param float `width_pct`: a number representing the `y` dock size constraint. 6315 """ 6316 6317 self._dock_constraint_x = max(0.0, min(1.0, width_pct)) 6318 self._dock_constraint_y = max(0.0, min(1.0, height_pct))
6319 6320
6321 - def GetDockSizeConstraint(self):
6322 """ 6323 Returns the current dock constraint values. 6324 6325 :see: :meth:`SetDockSizeConstraint` 6326 """ 6327 6328 return self._dock_constraint_x, self._dock_constraint_y
6329 6330
6331 - def Update(self):
6332 """ 6333 This method is called after any number of changes are made to any of the 6334 managed panes. :meth:`Update` must be invoked after :meth:`AddPane` 6335 or :meth:`InsertPane` are called in order to "realize" or "commit" the changes. 6336 6337 In addition, any number of changes may be made to :class:`AuiManager` structures 6338 (retrieved with :meth:`GetPane`), but to realize the changes, :meth:`Update` 6339 must be called. This construction allows pane flicker to be avoided by updating 6340 the whole layout at one time. 6341 """ 6342 6343 self._hover_button = None 6344 self._action_part = None 6345 6346 # destroy floating panes which have been 6347 # redocked or are becoming non-floating 6348 for p in self._panes: 6349 if p.IsFloating() or not p.frame: 6350 continue 6351 6352 # because the pane is no longer in a floating, we need to 6353 # reparent it to self._frame and destroy the floating frame 6354 # reduce flicker 6355 p.window.SetSize((1, 1)) 6356 6357 # the following block is a workaround for bug #1531361 6358 # (see wxWidgets sourceforge page). On wxGTK (only), when 6359 # a frame is shown/hidden, a move event unfortunately 6360 # also gets fired. Because we may be dragging around 6361 # a pane, we need to cancel that action here to prevent 6362 # a spurious crash. 6363 if self._action_window == p.frame: 6364 if self._frame.HasCapture(): 6365 self._frame.ReleaseMouse() 6366 self._action = actionNone 6367 self._action_window = None 6368 6369 # hide the frame 6370 if p.frame.IsShown(): 6371 p.frame.Show(False) 6372 6373 if self._action_window == p.frame: 6374 self._action_window = None 6375 6376 # reparent to self._frame and destroy the pane 6377 p.window.Reparent(self._frame) 6378 if isinstance(p.window, auibar.AuiToolBar): 6379 p.window.SetAuiManager(self) 6380 6381 if p.frame: 6382 p.frame.SetSizer(None) 6383 p.frame.Destroy() 6384 p.frame = None 6385 6386 # Only the master manager should create/destroy notebooks... 6387 if not self._masterManager: 6388 self.UpdateNotebook() 6389 6390 # delete old sizer first 6391 self._frame.SetSizer(None) 6392 6393 # create a layout for all of the panes 6394 sizer = self.LayoutAll(self._panes, self._docks, self._uiparts, False) 6395 6396 # hide or show panes as necessary, 6397 # and float panes as necessary 6398 6399 pane_count = len(self._panes) 6400 6401 for ii in xrange(pane_count): 6402 p = self._panes[ii] 6403 pFrame = p.frame 6404 6405 if p.IsFloating(): 6406 if pFrame is None: 6407 # we need to create a frame for this 6408 # pane, which has recently been floated 6409 frame = self.CreateFloatingFrame(self._frame, p) 6410 6411 # on MSW and Mac, if the owner desires transparent dragging, and 6412 # the dragging is happening right now, then the floating 6413 # window should have this style by default 6414 if self._action in [actionDragFloatingPane, actionDragToolbarPane] and \ 6415 self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: 6416 frame.SetTransparent(150) 6417 6418 if p.IsToolbar(): 6419 bar = p.window 6420 if isinstance(bar, auibar.AuiToolBar): 6421 bar.SetGripperVisible(False) 6422 agwStyle = bar.GetAGWWindowStyleFlag() 6423 bar.SetAGWWindowStyleFlag(agwStyle & ~AUI_TB_VERTICAL) 6424 bar.Realize() 6425 6426 s = p.window.GetMinSize() 6427 p.BestSize(s) 6428 p.FloatingSize(wx.DefaultSize) 6429 6430 frame.SetPaneWindow(p) 6431 p.needsTransparency = True 6432 p.frame = pFrame = frame 6433 if p.IsShown() and not frame.IsShown(): 6434 frame.Show() 6435 frame.Update() 6436 else: 6437 6438 # frame already exists, make sure it's position 6439 # and size reflect the information in AuiPaneInfo 6440 if pFrame.GetPosition() != p.floating_pos or pFrame.GetSize() != p.floating_size: 6441 pFrame.SetDimensions(p.floating_pos.x, p.floating_pos.y, 6442 p.floating_size.x, p.floating_size.y, wx.SIZE_USE_EXISTING) 6443 6444 # update whether the pane is resizable or not 6445 style = p.frame.GetWindowStyleFlag() 6446 if p.IsFixed(): 6447 style &= ~wx.RESIZE_BORDER 6448 else: 6449 style |= wx.RESIZE_BORDER 6450 6451 p.frame.SetWindowStyleFlag(style) 6452 6453 if pFrame.IsShown() != p.IsShown(): 6454 p.needsTransparency = True 6455 pFrame.Show(p.IsShown()) 6456 6457 if pFrame.GetTitle() != p.caption: 6458 pFrame.SetTitle(p.caption) 6459 if p.icon.IsOk(): 6460 pFrame.SetIcon(wx.IconFromBitmap(p.icon)) 6461 6462 else: 6463 6464 if p.IsToolbar(): 6465 # self.SwitchToolBarOrientation(p) 6466 p.best_size = p.window.GetBestSize() 6467 6468 if p.window and not p.IsNotebookPage() and p.window.IsShown() != p.IsShown(): 6469 p.window.Show(p.IsShown()) 6470 6471 if pFrame and p.needsTransparency: 6472 if pFrame.IsShown() and pFrame._transparent != p.transparent: 6473 pFrame.SetTransparent(p.transparent) 6474 pFrame._transparent = p.transparent 6475 6476 p.needsTransparency = False 6477 6478 # if "active panes" are no longer allowed, clear 6479 # any optionActive values from the pane states 6480 if self._agwFlags & AUI_MGR_ALLOW_ACTIVE_PANE == 0: 6481 p.state &= ~AuiPaneInfo.optionActive 6482 6483 self._panes[ii] = p 6484 6485 old_pane_rects = [] 6486 pane_count = len(self._panes) 6487 6488 for p in self._panes: 6489 r = wx.Rect() 6490 if p.window and p.IsShown() and p.IsDocked(): 6491 r = p.rect 6492 6493 old_pane_rects.append(r) 6494 6495 # apply the new sizer 6496 self._frame.SetSizer(sizer) 6497 self._frame.SetAutoLayout(False) 6498 self.DoFrameLayout() 6499 6500 # now that the frame layout is done, we need to check 6501 # the new pane rectangles against the old rectangles that 6502 # we saved a few lines above here. If the rectangles have 6503 # changed, the corresponding panes must also be updated 6504 for ii in xrange(pane_count): 6505 p = self._panes[ii] 6506 if p.window and p.IsShown() and p.IsDocked(): 6507 if p.rect != old_pane_rects[ii]: 6508 p.window.Refresh() 6509 p.window.Update() 6510 6511 if wx.Platform == "__WXMAC__": 6512 self._frame.Refresh() 6513 else: 6514 self.Repaint() 6515 6516 if not self._masterManager: 6517 e = self.FireEvent(wxEVT_AUI_PERSPECTIVE_CHANGED, None, canVeto=False)
6518 6519
6520 - def UpdateNotebook(self):
6521 """ Updates the automatic :class:`~lib.agw.aui.auibook.AuiNotebook` in the layout (if any exists). """ 6522 6523 # Workout how many notebooks we need. 6524 max_notebook = -1 6525 6526 # destroy floating panes which have been 6527 # redocked or are becoming non-floating 6528 for paneInfo in self._panes: 6529 if max_notebook < paneInfo.notebook_id: 6530 max_notebook = paneInfo.notebook_id 6531 6532 # We are the master of our domain 6533 extra_notebook = len(self._notebooks) 6534 max_notebook += 1 6535 6536 for i in xrange(extra_notebook, max_notebook): 6537 self.CreateNotebook() 6538 6539 # Remove pages from notebooks that no-longer belong there ... 6540 for nb, notebook in enumerate(self._notebooks): 6541 pages = notebook.GetPageCount() 6542 pageCounter, allPages = 0, pages 6543 6544 # Check each tab ... 6545 for page in xrange(pages): 6546 6547 if page >= allPages: 6548 break 6549 6550 window = notebook.GetPage(pageCounter) 6551 paneInfo = self.GetPane(window) 6552 if paneInfo.IsOk() and paneInfo.notebook_id != nb: 6553 notebook.RemovePage(pageCounter) 6554 window.Hide() 6555 window.Reparent(self._frame) 6556 pageCounter -= 1 6557 allPages -= 1 6558 6559 pageCounter += 1 6560 6561 notebook.DoSizing() 6562 6563 # Add notebook pages that aren't there already... 6564 for paneInfo in self._panes: 6565 if paneInfo.IsNotebookPage(): 6566 6567 title = (paneInfo.caption == "" and [paneInfo.name] or [paneInfo.caption])[0] 6568 6569 notebook = self._notebooks[paneInfo.notebook_id] 6570 page_id = notebook.GetPageIndex(paneInfo.window) 6571 6572 if page_id < 0: 6573 6574 paneInfo.window.Reparent(notebook) 6575 notebook.AddPage(paneInfo.window, title, True, paneInfo.icon) 6576 6577 # Update title and icon ... 6578 else: 6579 6580 notebook.SetPageText(page_id, title) 6581 notebook.SetPageBitmap(page_id, paneInfo.icon) 6582 6583 notebook.DoSizing() 6584 6585 # Wire-up newly created notebooks 6586 elif paneInfo.IsNotebookControl() and not paneInfo.window: 6587 paneInfo.window = self._notebooks[paneInfo.notebook_id] 6588 6589 # Delete empty notebooks, and convert notebooks with 1 page to 6590 # normal panes... 6591 remap_ids = [-1]*len(self._notebooks) 6592 nb_idx = 0 6593 6594 for nb, notebook in enumerate(self._notebooks): 6595 if notebook.GetPageCount() == 1: 6596 6597 # Convert notebook page to pane... 6598 window = notebook.GetPage(0) 6599 child_pane = self.GetPane(window) 6600 notebook_pane = self.GetPane(notebook) 6601 if child_pane.IsOk() and notebook_pane.IsOk(): 6602 6603 child_pane.SetDockPos(notebook_pane) 6604 child_pane.window.Hide() 6605 child_pane.window.Reparent(self._frame) 6606 child_pane.frame = None 6607 child_pane.notebook_id = -1 6608 if notebook_pane.IsFloating(): 6609 child_pane.Float() 6610 6611 self.DetachPane(notebook) 6612 6613 notebook.RemovePage(0) 6614 notebook.Destroy() 6615 6616 else: 6617 6618 raise Exception("Odd notebook docking") 6619 6620 elif notebook.GetPageCount() == 0: 6621 6622 self.DetachPane(notebook) 6623 notebook.Destroy() 6624 6625 else: 6626 6627 # Correct page ordering. The original wxPython code 6628 # for this did not work properly, and would misplace 6629 # windows causing errors. 6630 notebook.Freeze() 6631 self._notebooks[nb_idx] = notebook 6632 pages = notebook.GetPageCount() 6633 selected = notebook.GetPage(notebook.GetSelection()) 6634 6635 # Take each page out of the notebook, group it with 6636 # its current pane, and sort the list by pane.dock_pos 6637 # order 6638 pages_and_panes = [] 6639 for idx in reversed(range(pages)): 6640 page = notebook.GetPage(idx) 6641 pane = self.GetPane(page) 6642 pages_and_panes.append((page, pane)) 6643 notebook.RemovePage(idx) 6644 sorted_pnp = sorted(pages_and_panes, key=lambda tup: tup[1].dock_pos) 6645 6646 # Grab the attributes from the panes which are ordered 6647 # correctly, and copy those attributes to the original 6648 # panes. (This avoids having to change the ordering 6649 # of self._panes) Then, add the page back into the notebook 6650 sorted_attributes = [self.GetAttributes(tup[1]) 6651 for tup in sorted_pnp] 6652 for attrs, tup in zip(sorted_attributes, pages_and_panes): 6653 pane = tup[1] 6654 self.SetAttributes(pane, attrs) 6655 notebook.AddPage(pane.window, pane.caption) 6656 6657 notebook.SetSelection(notebook.GetPageIndex(selected), True) 6658 notebook.DoSizing() 6659 notebook.Thaw() 6660 6661 # It's a keeper. 6662 remap_ids[nb] = nb_idx 6663 nb_idx += 1 6664 6665 # Apply remap... 6666 nb_count = len(self._notebooks) 6667 6668 if nb_count != nb_idx: 6669 6670 self._notebooks = self._notebooks[0:nb_idx] 6671 for p in self._panes: 6672 if p.notebook_id >= 0: 6673 p.notebook_id = remap_ids[p.notebook_id] 6674 if p.IsNotebookControl(): 6675 p.SetNameFromNotebookId() 6676 6677 # Make sure buttons are correct ... 6678 for notebook in self._notebooks: 6679 want_max = True 6680 want_min = True 6681 want_close = True 6682 6683 pages = notebook.GetPageCount() 6684 for page in xrange(pages): 6685 6686 win = notebook.GetPage(page) 6687 pane = self.GetPane(win) 6688 if pane.IsOk(): 6689 6690 if not pane.HasCloseButton(): 6691 want_close = False 6692 if not pane.HasMaximizeButton(): 6693 want_max = False 6694 if not pane.HasMinimizeButton(): 6695 want_min = False 6696 6697 notebook_pane = self.GetPane(notebook) 6698 if notebook_pane.IsOk(): 6699 if notebook_pane.HasMinimizeButton() != want_min: 6700 if want_min: 6701 button = AuiPaneButton(AUI_BUTTON_MINIMIZE) 6702 notebook_pane.state |= AuiPaneInfo.buttonMinimize 6703 notebook_pane.buttons.append(button) 6704 6705 # todo: remove min/max 6706 6707 if notebook_pane.HasMaximizeButton() != want_max: 6708 if want_max: 6709 button = AuiPaneButton(AUI_BUTTON_MAXIMIZE_RESTORE) 6710 notebook_pane.state |= AuiPaneInfo.buttonMaximize 6711 notebook_pane.buttons.append(button) 6712 6713 # todo: remove min/max 6714 6715 if notebook_pane.HasCloseButton() != want_close: 6716 if want_close: 6717 button = AuiPaneButton(AUI_BUTTON_CLOSE) 6718 notebook_pane.state |= AuiPaneInfo.buttonClose 6719 notebook_pane.buttons.append(button)
6720 6721 # todo: remove close 6722 6723
6724 - def SmartShrink(self, docks, direction):
6725 """ 6726 Used to intelligently shrink the docks' size (if needed). 6727 6728 :param `docks`: a list of :class:`AuiDockInfo` instances; 6729 :param integer `direction`: the direction in which to shrink. 6730 """ 6731 6732 sashSize = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) 6733 caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) 6734 clientSize = self._frame.GetClientSize() 6735 ourDocks = FindDocks(docks, direction, -1, -1) 6736 oppositeDocks = FindOppositeDocks(docks, direction) 6737 oppositeSize = self.GetOppositeDockTotalSize(docks, direction) 6738 ourSize = 0 6739 6740 for dock in ourDocks: 6741 ourSize += dock.size 6742 6743 if not dock.toolbar: 6744 ourSize += sashSize 6745 6746 shrinkSize = ourSize + oppositeSize 6747 6748 if direction == AUI_DOCK_TOP or direction == AUI_DOCK_BOTTOM: 6749 shrinkSize -= clientSize.y 6750 else: 6751 shrinkSize -= clientSize.x 6752 6753 if shrinkSize <= 0: 6754 return docks 6755 6756 # Combine arrays 6757 for dock in oppositeDocks: 6758 ourDocks.append(dock) 6759 6760 oppositeDocks = [] 6761 6762 for dock in ourDocks: 6763 if dock.toolbar or not dock.resizable: 6764 continue 6765 6766 dockRange = dock.size - dock.min_size 6767 6768 if dock.min_size == 0: 6769 dockRange -= sashSize 6770 if direction == AUI_DOCK_TOP or direction == AUI_DOCK_BOTTOM: 6771 dockRange -= caption_size 6772 6773 if dockRange >= shrinkSize: 6774 6775 dock.size -= shrinkSize 6776 return docks 6777 6778 else: 6779 6780 dock.size -= dockRange 6781 shrinkSize -= dockRange 6782 6783 return docks
6784 6785
6786 - def UpdateDockingGuides(self, paneInfo):
6787 """ 6788 Updates the docking guide windows positions and appearance. 6789 6790 :param `paneInfo`: a :class:`AuiPaneInfo` instance. 6791 """ 6792 6793 if len(self._guides) == 0: 6794 self.CreateGuideWindows() 6795 6796 captionSize = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) 6797 frameRect = GetInternalFrameRect(self._frame, self._docks) 6798 mousePos = wx.GetMousePosition() 6799 6800 for indx, guide in enumerate(self._guides): 6801 6802 pt = wx.Point() 6803 guide_size = guide.host.GetSize() 6804 if not guide.host: 6805 raise Exception("Invalid docking host") 6806 6807 direction = guide.dock_direction 6808 6809 if direction == AUI_DOCK_LEFT: 6810 pt.x = frameRect.x + guide_size.x / 2 + 16 6811 pt.y = frameRect.y + frameRect.height / 2 6812 6813 elif direction == AUI_DOCK_TOP: 6814 pt.x = frameRect.x + frameRect.width / 2 6815 pt.y = frameRect.y + guide_size.y / 2 + 16 6816 6817 elif direction == AUI_DOCK_RIGHT: 6818 pt.x = frameRect.x + frameRect.width - guide_size.x / 2 - 16 6819 pt.y = frameRect.y + frameRect.height / 2 6820 6821 elif direction == AUI_DOCK_BOTTOM: 6822 pt.x = frameRect.x + frameRect.width / 2 6823 pt.y = frameRect.y + frameRect.height - guide_size.y / 2 - 16 6824 6825 elif direction == AUI_DOCK_CENTER: 6826 rc = paneInfo.window.GetScreenRect() 6827 pt.x = rc.x + rc.width / 2 6828 pt.y = rc.y + rc.height / 2 6829 if paneInfo.HasCaption(): 6830 pt.y -= captionSize / 2 6831 elif paneInfo.HasCaptionLeft(): 6832 pt.x -= captionSize / 2 6833 6834 # guide will be centered around point 'pt' 6835 targetPosition = wx.Point(pt.x - guide_size.x / 2, pt.y - guide_size.y / 2) 6836 6837 if guide.host.GetPosition() != targetPosition: 6838 guide.host.Move(targetPosition) 6839 6840 guide.host.AeroMove(targetPosition) 6841 6842 if guide.dock_direction == AUI_DOCK_CENTER: 6843 guide.host.ValidateNotebookDocking(paneInfo.IsNotebookDockable()) 6844 6845 guide.host.UpdateDockGuide(mousePos) 6846 6847 paneInfo.window.Lower()
6848 6849
6850 - def DoFrameLayout(self):
6851 """ 6852 This is an internal function which invokes :meth:`Sizer.Layout() <Sizer.Layout>` 6853 on the frame's main sizer, then measures all the various UI items 6854 and updates their internal rectangles. 6855 6856 :note: This should always be called instead of calling 6857 `self._managed_window.Layout()` directly. 6858 """ 6859 6860 self._frame.Layout() 6861 6862 for part in self._uiparts: 6863 # get the rectangle of the UI part 6864 # originally, this code looked like this: 6865 # part.rect = wx.Rect(part.sizer_item.GetPosition(), 6866 # part.sizer_item.GetSize()) 6867 # this worked quite well, with one exception: the mdi 6868 # client window had a "deferred" size variable 6869 # that returned the wrong size. It looks like 6870 # a bug in wx, because the former size of the window 6871 # was being returned. So, we will retrieve the part's 6872 # rectangle via other means 6873 6874 part.rect = part.sizer_item.GetRect() 6875 flag = part.sizer_item.GetFlag() 6876 border = part.sizer_item.GetBorder() 6877 6878 if flag & wx.TOP: 6879 part.rect.y -= border 6880 part.rect.height += border 6881 if flag & wx.LEFT: 6882 part.rect.x -= border 6883 part.rect.width += border 6884 if flag & wx.BOTTOM: 6885 part.rect.height += border 6886 if flag & wx.RIGHT: 6887 part.rect.width += border 6888 6889 if part.type == AuiDockUIPart.typeDock: 6890 part.dock.rect = part.rect 6891 if part.type == AuiDockUIPart.typePane: 6892 part.pane.rect = part.rect
6893 6894
6895 - def GetPanePart(self, wnd):
6896 """ 6897 Looks up the pane border UI part of the 6898 pane specified. This allows the caller to get the exact rectangle 6899 of the pane in question, including decorations like caption and border. 6900 6901 :param Window `wnd`: the window to which the pane border belongs to. 6902 """ 6903 6904 for part in self._uiparts: 6905 if part.type == AuiDockUIPart.typePaneBorder and \ 6906 part.pane and part.pane.window == wnd: 6907 return part 6908 6909 for part in self._uiparts: 6910 if part.type == AuiDockUIPart.typePane and \ 6911 part.pane and part.pane.window == wnd: 6912 return part 6913 6914 return None
6915 6916
6917 - def GetDockPixelOffset(self, test):
6918 """ 6919 This is an internal function which returns a dock's offset in pixels from 6920 the left side of the window (for horizontal docks) or from the top of the 6921 window (for vertical docks). 6922 6923 This value is necessary for calculating fixed-pane/toolbar offsets 6924 when they are dragged. 6925 6926 :param `test`: a fake :class:`AuiPaneInfo` for testing purposes. 6927 """ 6928 6929 # the only way to accurately calculate the dock's 6930 # offset is to actually run a theoretical layout 6931 docks, panes = CopyDocksAndPanes2(self._docks, self._panes) 6932 panes.append(test) 6933 6934 sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False) 6935 client_size = self._frame.GetClientSize() 6936 sizer.SetDimension(0, 0, client_size.x, client_size.y) 6937 sizer.Layout() 6938 6939 for part in uiparts: 6940 pos = part.sizer_item.GetPosition() 6941 size = part.sizer_item.GetSize() 6942 part.rect = wx.RectPS(pos, size) 6943 if part.type == AuiDockUIPart.typeDock: 6944 part.dock.rect = part.rect 6945 6946 sizer.Destroy() 6947 6948 for dock in docks: 6949 if test.dock_direction == dock.dock_direction and \ 6950 test.dock_layer == dock.dock_layer and \ 6951 test.dock_row == dock.dock_row: 6952 6953 if dock.IsVertical(): 6954 return dock.rect.y 6955 else: 6956 return dock.rect.x 6957 6958 return 0
6959 6960
6961 - def GetPartnerDock(self, dock):
6962 """ 6963 Returns the partner dock for the input dock. 6964 6965 :param `dock`: a :class:`AuiDockInfo` instance. 6966 """ 6967 6968 for layer in xrange(dock.dock_layer, -1, -1): 6969 6970 bestDock = None 6971 6972 for tmpDock in self._docks: 6973 6974 if tmpDock.dock_layer != layer: 6975 continue 6976 6977 if tmpDock.dock_direction != dock.dock_direction: 6978 continue 6979 6980 if tmpDock.dock_layer < dock.dock_layer: 6981 6982 if not bestDock or tmpDock.dock_row < bestDock.dock_row: 6983 bestDock = tmpDock 6984 6985 elif tmpDock.dock_row > dock.dock_row: 6986 6987 if not bestDock or tmpDock.dock_row > bestDock.dock_row: 6988 bestDock = tmpDock 6989 6990 if bestDock: 6991 return bestDock 6992 6993 return None
6994 6995
6996 - def GetPartnerPane(self, dock, pane):
6997 """ 6998 Returns the partner pane for the input pane. They both need to live 6999 in the same :class:`AuiDockInfo`. 7000 7001 :param `dock`: a :class:`AuiDockInfo` instance; 7002 :param `pane`: a :class:`AuiPaneInfo` class. 7003 """ 7004 7005 panePosition = -1 7006 7007 for i, tmpPane in enumerate(dock.panes): 7008 if tmpPane.window == pane.window: 7009 panePosition = i 7010 elif not tmpPane.IsFixed() and panePosition != -1: 7011 return tmpPane 7012 7013 return None
7014 7015
7016 - def GetTotalPixSizeAndProportion(self, dock):
7017 """ 7018 Returns the dimensions and proportion of the input dock. 7019 7020 :param `dock`: the :class:`AuiDockInfo` structure to analyze. 7021 """ 7022 7023 totalPixsize = 0 7024 totalProportion = 0 7025 7026 # determine the total proportion of all resizable panes, 7027 # and the total size of the dock minus the size of all 7028 # the fixed panes 7029 for tmpPane in dock.panes: 7030 7031 if tmpPane.IsFixed(): 7032 continue 7033 7034 totalProportion += tmpPane.dock_proportion 7035 7036 if dock.IsHorizontal(): 7037 totalPixsize += tmpPane.rect.width 7038 else: 7039 totalPixsize += tmpPane.rect.height 7040 7041 ## if tmpPane.min_size.IsFullySpecified(): 7042 ## 7043 ## if dock.IsHorizontal(): 7044 ## totalPixsize -= tmpPane.min_size.x 7045 ## else: 7046 ## totalPixsize -= tmpPane.min_size.y 7047 7048 return totalPixsize, totalProportion
7049 7050
7051 - def GetOppositeDockTotalSize(self, docks, direction):
7052 """ 7053 Returns the dimensions of the dock which lives opposite of the input dock. 7054 7055 :param `docks`: a list of :class:`AuiDockInfo` structures to analyze; 7056 :param integer `direction`: the direction in which to look for the opposite dock. 7057 """ 7058 7059 sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) 7060 caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) 7061 pane_border_size = self._art.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE) 7062 minSizeMax = 0 7063 result = sash_size 7064 vertical = False 7065 7066 if direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]: 7067 vertical = True 7068 7069 # Get minimum size of the most inner area 7070 for tmpDock in docks: 7071 7072 if tmpDock.dock_layer != 0: 7073 continue 7074 7075 if tmpDock.dock_direction != AUI_DOCK_CENTER and tmpDock.IsVertical() != vertical: 7076 continue 7077 7078 for tmpPane in tmpDock.panes: 7079 7080 minSize = pane_border_size*2 - sash_size 7081 7082 if vertical: 7083 minSize += tmpPane.min_size.y + caption_size 7084 else: 7085 minSize += tmpPane.min_size.x 7086 7087 if minSize > minSizeMax: 7088 minSizeMax = minSize 7089 7090 result += minSizeMax 7091 7092 # Get opposite docks 7093 oppositeDocks = FindOppositeDocks(docks, direction) 7094 7095 # Sum size of the opposite docks and their sashes 7096 for dock in oppositeDocks: 7097 result += dock.size 7098 # if it's not a toolbar add the sash_size too 7099 if not dock.toolbar: 7100 result += sash_size 7101 7102 return result
7103 7104
7105 - def CalculateDockSizerLimits(self, dock):
7106 """ 7107 Calculates the minimum and maximum sizes allowed for the input dock. 7108 7109 :param `dock`: the :class:`AuiDockInfo` structure to analyze. 7110 """ 7111 7112 docks, panes = CopyDocksAndPanes2(self._docks, self._panes) 7113 7114 sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) 7115 caption_size = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) 7116 opposite_size = self.GetOppositeDockTotalSize(docks, dock.dock_direction) 7117 7118 for tmpDock in docks: 7119 7120 if tmpDock.dock_direction == dock.dock_direction and \ 7121 tmpDock.dock_layer == dock.dock_layer and \ 7122 tmpDock.dock_row == dock.dock_row: 7123 7124 tmpDock.size = 1 7125 break 7126 7127 sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False) 7128 client_size = self._frame.GetClientSize() 7129 sizer.SetDimension(0, 0, client_size.x, client_size.y) 7130 sizer.Layout() 7131 7132 for part in uiparts: 7133 7134 part.rect = wx.RectPS(part.sizer_item.GetPosition(), part.sizer_item.GetSize()) 7135 if part.type == AuiDockUIPart.typeDock: 7136 part.dock.rect = part.rect 7137 7138 sizer.Destroy() 7139 new_dock = None 7140 7141 for tmpDock in docks: 7142 if tmpDock.dock_direction == dock.dock_direction and \ 7143 tmpDock.dock_layer == dock.dock_layer and \ 7144 tmpDock.dock_row == dock.dock_row: 7145 7146 new_dock = tmpDock 7147 break 7148 7149 partnerDock = self.GetPartnerDock(dock) 7150 7151 if partnerDock: 7152 partnerRange = partnerDock.size - partnerDock.min_size 7153 if partnerDock.min_size == 0: 7154 partnerRange -= sash_size 7155 if dock.IsHorizontal(): 7156 partnerRange -= caption_size 7157 7158 direction = dock.dock_direction 7159 7160 if direction == AUI_DOCK_LEFT: 7161 minPix = new_dock.rect.x + new_dock.rect.width 7162 maxPix = dock.rect.x + dock.rect.width 7163 maxPix += partnerRange 7164 7165 elif direction == AUI_DOCK_TOP: 7166 minPix = new_dock.rect.y + new_dock.rect.height 7167 maxPix = dock.rect.y + dock.rect.height 7168 maxPix += partnerRange 7169 7170 elif direction == AUI_DOCK_RIGHT: 7171 minPix = dock.rect.x - partnerRange - sash_size 7172 maxPix = new_dock.rect.x - sash_size 7173 7174 elif direction == AUI_DOCK_BOTTOM: 7175 minPix = dock.rect.y - partnerRange - sash_size 7176 maxPix = new_dock.rect.y - sash_size 7177 7178 return minPix, maxPix 7179 7180 direction = new_dock.dock_direction 7181 7182 if direction == AUI_DOCK_LEFT: 7183 minPix = new_dock.rect.x + new_dock.rect.width 7184 maxPix = client_size.x - opposite_size - sash_size 7185 7186 elif direction == AUI_DOCK_TOP: 7187 minPix = new_dock.rect.y + new_dock.rect.height 7188 maxPix = client_size.y - opposite_size - sash_size 7189 7190 elif direction == AUI_DOCK_RIGHT: 7191 minPix = opposite_size 7192 maxPix = new_dock.rect.x - sash_size 7193 7194 elif direction == AUI_DOCK_BOTTOM: 7195 minPix = opposite_size 7196 maxPix = new_dock.rect.y - sash_size 7197 7198 return minPix, maxPix
7199 7200
7201 - def CalculatePaneSizerLimits(self, dock, pane):
7202 """ 7203 Calculates the minimum and maximum sizes allowed for the input pane. 7204 7205 :param `dock`: the :class:`AuiDockInfo` structure to which `pane` belongs to; 7206 :param `pane`: a :class:`AuiPaneInfo` class for which calculation are requested. 7207 """ 7208 7209 if pane.IsFixed(): 7210 if dock.IsHorizontal(): 7211 minPix = maxPix = pane.rect.x + 1 + pane.rect.width 7212 else: 7213 minPix = maxPix = pane.rect.y + 1 + pane.rect.height 7214 7215 return minPix, maxPix 7216 7217 totalPixsize, totalProportion = self.GetTotalPixSizeAndProportion(dock) 7218 partnerPane = self.GetPartnerPane(dock, pane) 7219 7220 if dock.IsHorizontal(): 7221 7222 minPix = pane.rect.x + 1 7223 maxPix = pane.rect.x + 1 + pane.rect.width 7224 7225 if pane.min_size.IsFullySpecified(): 7226 minPix += pane.min_size.x 7227 else: 7228 minPix += 1 7229 7230 if partnerPane: 7231 maxPix += partnerPane.rect.width 7232 7233 if partnerPane.min_size.IsFullySpecified(): 7234 maxPix -= partnerPane.min_size.x - 1 7235 7236 else: 7237 minPix = maxPix 7238 7239 else: 7240 7241 minPix = pane.rect.y + 1 7242 maxPix = pane.rect.y + 1 + pane.rect.height 7243 7244 if pane.min_size.IsFullySpecified(): 7245 minPix += pane.min_size.y 7246 else: 7247 minPix += 1 7248 7249 if partnerPane: 7250 maxPix += partnerPane.rect.height 7251 7252 if partnerPane.min_size.IsFullySpecified(): 7253 maxPix -= partnerPane.min_size.y - 1 7254 7255 else: 7256 minPix = maxPix 7257 7258 return minPix, maxPix
7259 7260
7261 - def CheckMovableSizer(self, part):
7262 """ 7263 Checks if a UI part can be actually resized. 7264 7265 :param AuiDockUIPart `part`: a UI part. 7266 """ 7267 7268 # a dock may not be resized if it has a single 7269 # pane which is not resizable 7270 if part.type == AuiDockUIPart.typeDockSizer and part.dock and \ 7271 len(part.dock.panes) == 1 and part.dock.panes[0].IsFixed(): 7272 7273 return False 7274 7275 if part.pane: 7276 7277 # panes that may not be resized should be ignored here 7278 minPix, maxPix = self.CalculatePaneSizerLimits(part.dock, part.pane) 7279 7280 if minPix == maxPix: 7281 return False 7282 7283 return True
7284 7285
7286 - def PaneFromTabEvent(self, event):
7287 """ 7288 Returns a :class:`AuiPaneInfo` from a :class:`~lib.agw.aui.auibook.AuiNotebook` event. 7289 7290 :param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event. 7291 """ 7292 7293 obj = event.GetEventObject() 7294 7295 if obj and isinstance(obj, auibook.AuiTabCtrl): 7296 7297 page_idx = obj.GetActivePage() 7298 7299 if page_idx >= 0: 7300 page = obj.GetPage(page_idx) 7301 window = page.window 7302 if window: 7303 return self.GetPane(window) 7304 7305 elif obj and isinstance(obj, auibook.AuiNotebook): 7306 7307 page_idx = event.GetSelection() 7308 7309 if page_idx >= 0: 7310 window = obj.GetPage(page_idx) 7311 if window: 7312 return self.GetPane(window) 7313 7314 return NonePaneInfo
7315 7316
7317 - def OnTabBeginDrag(self, event):
7318 """ 7319 Handles the ``EVT_AUINOTEBOOK_BEGIN_DRAG`` event. 7320 7321 :param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event to be processed. 7322 """ 7323 7324 if self._masterManager: 7325 self._masterManager.OnTabBeginDrag(event) 7326 7327 else: 7328 paneInfo = self.PaneFromTabEvent(event) 7329 7330 if paneInfo.IsOk(): 7331 7332 # It's one of ours! 7333 self._action = actionDragFloatingPane 7334 mouse = wx.GetMousePosition() 7335 7336 # set initial float position - may have to think about this 7337 # offset a bit more later ... 7338 self._action_offset = wx.Point(20, 10) 7339 self._toolbar_action_offset = wx.Point(20, 10) 7340 7341 paneInfo.floating_pos = mouse - self._action_offset 7342 paneInfo.dock_pos = AUI_DOCK_NONE 7343 paneInfo.notebook_id = -1 7344 7345 tab = event.GetEventObject() 7346 7347 if tab.HasCapture(): 7348 tab.ReleaseMouse() 7349 7350 # float the window 7351 if paneInfo.IsMaximized(): 7352 self.RestorePane(paneInfo) 7353 paneInfo.Float() 7354 self.Update() 7355 7356 self._action_window = paneInfo.window 7357 7358 self._frame.CaptureMouse() 7359 event.SetDispatched(True) 7360 7361 else: 7362 7363 # not our window 7364 event.Skip()
7365 7366
7367 - def OnTabPageClose(self, event):
7368 """ 7369 Handles the ``EVT_AUINOTEBOOK_PAGE_CLOSE`` event. 7370 7371 :param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event to be processed. 7372 """ 7373 7374 if self._masterManager: 7375 self._masterManager.OnTabPageClose(event) 7376 7377 else: 7378 7379 p = self.PaneFromTabEvent(event) 7380 if p.IsOk(): 7381 7382 # veto it because we will call "RemovePage" ourselves 7383 event.Veto() 7384 7385 # Now ask the app if they really want to close... 7386 # fire pane close event 7387 e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE) 7388 e.SetPane(p) 7389 e.SetCanVeto(True) 7390 self.ProcessMgrEvent(e) 7391 7392 if e.GetVeto(): 7393 return 7394 7395 self.ClosePane(p) 7396 self.Update() 7397 else: 7398 event.Skip()
7399 7400
7401 - def OnTabSelected(self, event):
7402 """ 7403 Handles the ``EVT_AUINOTEBOOK_PAGE_CHANGED`` event. 7404 7405 :param `event`: a :class:`~lib.agw.aui.auibook.AuiNotebookEvent` event to be processed. 7406 """ 7407 7408 if self._masterManager: 7409 self._masterManager.OnTabSelected(event) 7410 return 7411 7412 obj = event.GetEventObject() 7413 7414 if obj and isinstance(obj, auibook.AuiNotebook): 7415 7416 notebook = obj 7417 page = notebook.GetPage(event.GetSelection()) 7418 paneInfo = self.GetPane(page) 7419 7420 if paneInfo.IsOk(): 7421 notebookRoot = GetNotebookRoot(self._panes, paneInfo.notebook_id) 7422 if notebookRoot: 7423 7424 notebookRoot.Caption(paneInfo.caption) 7425 self.RefreshCaptions() 7426 7427 event.Skip()
7428 7429
7430 - def GetNotebooks(self):
7431 """ Returns all the automatic :class:`~lib.agw.aui.auibook.AuiNotebook` in the :class:`AuiManager`. """ 7432 7433 if self._masterManager: 7434 return self._masterManager.GetNotebooks() 7435 7436 return self._notebooks
7437 7438
7439 - def SetMasterManager(self, manager):
7440 """ 7441 Sets the master manager for an automatic :class:`~lib.agw.aui.auibook.AuiNotebook`. 7442 7443 :param `manager`: an instance of :class:`AuiManager`. 7444 """ 7445 7446 self._masterManager = manager
7447 7448
7449 - def ProcessDockResult(self, target, new_pos):
7450 """ 7451 This is a utility function used by :meth:`DoDrop` - it checks 7452 if a dock operation is allowed, the new dock position is copied into 7453 the target info. If the operation was allowed, the function returns ``True``. 7454 7455 :param `target`: the :class:`AuiPaneInfo` instance to be docked; 7456 :param integer `new_pos`: the new docking position if the docking operation is allowed. 7457 """ 7458 7459 allowed = False 7460 direction = new_pos.dock_direction 7461 7462 if direction == AUI_DOCK_TOP: 7463 allowed = target.IsTopDockable() 7464 elif direction == AUI_DOCK_BOTTOM: 7465 allowed = target.IsBottomDockable() 7466 elif direction == AUI_DOCK_LEFT: 7467 allowed = target.IsLeftDockable() 7468 elif direction == AUI_DOCK_RIGHT: 7469 allowed = target.IsRightDockable() 7470 7471 if allowed: 7472 target = new_pos 7473 7474 if target.IsToolbar(): 7475 self.SwitchToolBarOrientation(target) 7476 7477 return allowed, target
7478 7479
7480 - def SwitchToolBarOrientation(self, pane):
7481 """ 7482 Switches the toolbar orientation from vertical to horizontal and vice-versa. 7483 This is especially useful for vertical docked toolbars once they float. 7484 7485 :param `pane`: an instance of :class:`AuiPaneInfo`, which may have a :class:`~lib.agw.aui.auibar.AuiToolBar` 7486 window associated with it. 7487 """ 7488 7489 if not isinstance(pane.window, auibar.AuiToolBar): 7490 return pane 7491 7492 if pane.IsFloating(): 7493 return pane 7494 7495 toolBar = pane.window 7496 direction = pane.dock_direction 7497 vertical = direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT] 7498 7499 agwStyle = toolBar.GetAGWWindowStyleFlag() 7500 new_agwStyle = agwStyle 7501 7502 if vertical: 7503 new_agwStyle |= AUI_TB_VERTICAL 7504 else: 7505 new_agwStyle &= ~(AUI_TB_VERTICAL) 7506 7507 if agwStyle != new_agwStyle: 7508 toolBar.SetAGWWindowStyleFlag(new_agwStyle) 7509 if not toolBar.GetGripperVisible(): 7510 toolBar.SetGripperVisible(True) 7511 7512 s = pane.window.GetMinSize() 7513 pane.BestSize(s) 7514 7515 if new_agwStyle != agwStyle: 7516 toolBar.Realize() 7517 7518 return pane
7519 7520
7521 - def DoDrop(self, docks, panes, target, pt, offset=wx.Point(0, 0)):
7522 """ 7523 This is an important function. It basically takes a mouse position, 7524 and determines where the panes new position would be. If the pane is to be 7525 dropped, it performs the drop operation using the specified dock and pane 7526 arrays. By specifying copy dock and pane arrays when calling, a "what-if" 7527 scenario can be performed, giving precise coordinates for drop hints. 7528 7529 :param `docks`: a list of :class:`AuiDockInfo` classes; 7530 :param `panes`: a list of :class:`AuiPaneInfo` instances; 7531 :param Point `pt`: a mouse position to check for a drop operation; 7532 :param Point `offset`: a possible offset from the input point `pt`. 7533 """ 7534 7535 if target.IsToolbar(): 7536 return self.DoDropToolbar(docks, panes, target, pt, offset) 7537 elif target.IsFloating(): 7538 return self.DoDropFloatingPane(docks, panes, target, pt) 7539 else: 7540 return self.DoDropNonFloatingPane(docks, panes, target, pt)
7541 7542
7543 - def CopyTarget(self, target):
7544 """ 7545 Copies all the attributes of the input `target` into another :class:`AuiPaneInfo`. 7546 7547 :param `target`: the source :class:`AuiPaneInfo` from where to copy attributes. 7548 """ 7549 7550 drop = AuiPaneInfo() 7551 drop.name = target.name 7552 drop.caption = target.caption 7553 drop.window = target.window 7554 drop.frame = target.frame 7555 drop.state = target.state 7556 drop.dock_direction = target.dock_direction 7557 drop.dock_layer = target.dock_layer 7558 drop.dock_row = target.dock_row 7559 drop.dock_pos = target.dock_pos 7560 drop.best_size = wx.Size(*target.best_size) 7561 drop.min_size = wx.Size(*target.min_size) 7562 drop.max_size = wx.Size(*target.max_size) 7563 drop.floating_pos = wx.Point(*target.floating_pos) 7564 drop.floating_size = wx.Size(*target.floating_size) 7565 drop.dock_proportion = target.dock_proportion 7566 drop.buttons = target.buttons 7567 drop.rect = wx.Rect(*target.rect) 7568 drop.icon = target.icon 7569 drop.notebook_id = target.notebook_id 7570 drop.transparent = target.transparent 7571 drop.snapped = target.snapped 7572 drop.minimize_mode = target.minimize_mode 7573 drop.minimize_target = target.minimize_target 7574 7575 return drop
7576 7577
7578 - def DoDropToolbar(self, docks, panes, target, pt, offset):
7579 """ 7580 Handles the situation in which the dropped pane contains a toolbar. 7581 7582 :param `docks`: a list of :class:`AuiDockInfo` classes; 7583 :param `panes`: a list of :class:`AuiPaneInfo` instances; 7584 :param AuiPaneInfo `target`: the target pane containing the toolbar; 7585 :param Point `pt`: a mouse position to check for a drop operation; 7586 :param Point `offset`: a possible offset from the input point `pt`. 7587 """ 7588 7589 drop = self.CopyTarget(target) 7590 7591 # The result should always be shown 7592 drop.Show() 7593 7594 # Check to see if the toolbar has been dragged out of the window 7595 if CheckOutOfWindow(self._frame, pt): 7596 if self._agwFlags & AUI_MGR_ALLOW_FLOATING and drop.IsFloatable(): 7597 drop.Float() 7598 7599 return self.ProcessDockResult(target, drop) 7600 7601 # Allow directional change when the cursor leaves this rect 7602 safeRect = wx.Rect(*target.rect) 7603 if target.IsHorizontal(): 7604 safeRect.Inflate(100, 50) 7605 else: 7606 safeRect.Inflate(50, 100) 7607 7608 # Check to see if the toolbar has been dragged to edge of the frame 7609 dropDir = CheckEdgeDrop(self._frame, docks, pt) 7610 7611 if dropDir != -1: 7612 7613 if dropDir == wx.LEFT: 7614 drop.Dock().Left().Layer(auiToolBarLayer).Row(0). \ 7615 Position(pt.y - self.GetDockPixelOffset(drop) - offset.y) 7616 7617 elif dropDir == wx.RIGHT: 7618 drop.Dock().Right().Layer(auiToolBarLayer).Row(0). \ 7619 Position(pt.y - self.GetDockPixelOffset(drop) - offset.y) 7620 7621 elif dropDir == wx.TOP: 7622 drop.Dock().Top().Layer(auiToolBarLayer).Row(0). \ 7623 Position(pt.x - self.GetDockPixelOffset(drop) - offset.x) 7624 7625 elif dropDir == wx.BOTTOM: 7626 drop.Dock().Bottom().Layer(auiToolBarLayer).Row(0). \ 7627 Position(pt.x - self.GetDockPixelOffset(drop) - offset.x) 7628 7629 if not target.IsFloating() and safeRect.Contains(pt) and \ 7630 target.dock_direction != drop.dock_direction: 7631 return False, target 7632 7633 return self.ProcessDockResult(target, drop) 7634 7635 # If the windows is floating and out of the client area, do nothing 7636 if drop.IsFloating() and not self._frame.GetClientRect().Contains(pt): 7637 return False, target 7638 7639 # Ok, can't drop on edge - check internals ... 7640 7641 clientSize = self._frame.GetClientSize() 7642 x = Clip(pt.x, 0, clientSize.x - 1) 7643 y = Clip(pt.y, 0, clientSize.y - 1) 7644 part = self.HitTest(x, y) 7645 7646 if not part or not part.dock: 7647 return False, target 7648 7649 dock = part.dock 7650 7651 # toolbars may only be moved in and to fixed-pane docks, 7652 # otherwise we will try to float the pane. Also, the pane 7653 # should float if being dragged over center pane windows 7654 if not dock.fixed or dock.dock_direction == AUI_DOCK_CENTER: 7655 7656 if (self._agwFlags & AUI_MGR_ALLOW_FLOATING and drop.IsFloatable()) or \ 7657 dock.dock_direction not in [AUI_DOCK_CENTER, AUI_DOCK_NONE]: 7658 if drop.IsFloatable(): 7659 drop.Float() 7660 7661 return self.ProcessDockResult(target, drop) 7662 7663 # calculate the offset from where the dock begins 7664 # to the point where the user dropped the pane 7665 dockDropOffset = 0 7666 if dock.IsHorizontal(): 7667 dockDropOffset = pt.x - dock.rect.x - offset.x 7668 else: 7669 dockDropOffset = pt.y - dock.rect.y - offset.y 7670 7671 drop.Dock().Direction(dock.dock_direction).Layer(dock.dock_layer). \ 7672 Row(dock.dock_row).Position(dockDropOffset) 7673 7674 if (pt.y <= dock.rect.GetTop() + 2 and dock.IsHorizontal()) or \ 7675 (pt.x <= dock.rect.GetLeft() + 2 and dock.IsVertical()): 7676 7677 if dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]: 7678 row = drop.dock_row 7679 panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row) 7680 drop.dock_row = row 7681 7682 else: 7683 panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row+1) 7684 drop.dock_row = dock.dock_row + 1 7685 7686 if (pt.y >= dock.rect.GetBottom() - 2 and dock.IsHorizontal()) or \ 7687 (pt.x >= dock.rect.GetRight() - 2 and dock.IsVertical()): 7688 7689 if dock.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_LEFT]: 7690 panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row+1) 7691 drop.dock_row = dock.dock_row+1 7692 7693 else: 7694 row = drop.dock_row 7695 panes = DoInsertDockRow(panes, dock.dock_direction, dock.dock_layer, dock.dock_row) 7696 drop.dock_row = row 7697 7698 if not target.IsFloating() and safeRect.Contains(pt) and \ 7699 target.dock_direction != drop.dock_direction: 7700 return False, target 7701 7702 return self.ProcessDockResult(target, drop)
7703 7704
7705 - def DoDropFloatingPane(self, docks, panes, target, pt):
7706 """ 7707 Handles the situation in which the dropped pane contains a normal window. 7708 7709 :param `docks`: a list of :class:`AuiDockInfo` classes; 7710 :param `panes`: a list of :class:`AuiPaneInfo` instances; 7711 :param AuiPaneInfo `target`: the target pane containing the window; 7712 :param Point `pt`: a mouse position to check for a drop operation. 7713 """ 7714 7715 screenPt = self._frame.ClientToScreen(pt) 7716 paneInfo = self.PaneHitTest(panes, pt) 7717 7718 if paneInfo.IsMaximized(): 7719 return False, target 7720 7721 if paneInfo.window is None: 7722 return False, target 7723 7724 # search the dock guides. 7725 # reverse order to handle the center first. 7726 for i in xrange(len(self._guides)-1, -1, -1): 7727 guide = self._guides[i] 7728 7729 # do hit testing on the guide 7730 dir = guide.host.HitTest(screenPt.x, screenPt.y) 7731 7732 if dir == -1: # point was outside of the dock guide 7733 continue 7734 7735 if dir == wx.ALL: # target is a single dock guide 7736 return self.DoDropLayer(docks, target, guide.dock_direction) 7737 7738 elif dir == wx.CENTER: 7739 7740 if not target.IsNotebookDockable(): 7741 continue 7742 if not paneInfo.IsNotebookDockable() and not paneInfo.IsNotebookControl(): 7743 continue 7744 7745 if not paneInfo.HasNotebook(): 7746 7747 # Add a new notebook pane with the original as a tab... 7748 self.CreateNotebookBase(panes, paneInfo) 7749 7750 # Add new item to notebook 7751 target.NotebookPage(paneInfo.notebook_id) 7752 7753 else: 7754 7755 drop_pane = False 7756 drop_row = False 7757 7758 insert_dir = paneInfo.dock_direction 7759 insert_layer = paneInfo.dock_layer 7760 insert_row = paneInfo.dock_row 7761 insert_pos = paneInfo.dock_pos 7762 7763 if insert_dir == AUI_DOCK_CENTER: 7764 7765 insert_layer = 0 7766 if dir == wx.LEFT: 7767 insert_dir = AUI_DOCK_LEFT 7768 elif dir == wx.UP: 7769 insert_dir = AUI_DOCK_TOP 7770 elif dir == wx.RIGHT: 7771 insert_dir = AUI_DOCK_RIGHT 7772 elif dir == wx.DOWN: 7773 insert_dir = AUI_DOCK_BOTTOM 7774 7775 if insert_dir == AUI_DOCK_LEFT: 7776 7777 drop_pane = (dir == wx.UP or dir == wx.DOWN) 7778 drop_row = (dir == wx.LEFT or dir == wx.RIGHT) 7779 if dir == wx.RIGHT: 7780 insert_row += 1 7781 elif dir == wx.DOWN: 7782 insert_pos += 1 7783 7784 elif insert_dir == AUI_DOCK_RIGHT: 7785 7786 drop_pane = (dir == wx.UP or dir == wx.DOWN) 7787 drop_row = (dir == wx.LEFT or dir == wx.RIGHT) 7788 if dir == wx.LEFT: 7789 insert_row += 1 7790 elif dir == wx.DOWN: 7791 insert_pos += 1 7792 7793 elif insert_dir == AUI_DOCK_TOP: 7794 7795 drop_pane = (dir == wx.LEFT or dir == wx.RIGHT) 7796 drop_row = (dir == wx.UP or dir == wx.DOWN) 7797 if dir == wx.DOWN: 7798 insert_row += 1 7799 elif dir == wx.RIGHT: 7800 insert_pos += 1 7801 7802 elif insert_dir == AUI_DOCK_BOTTOM: 7803 7804 drop_pane = (dir == wx.LEFT or dir == wx.RIGHT) 7805 drop_row = (dir == wx.UP or dir == wx.DOWN) 7806 if dir == wx.UP: 7807 insert_row += 1 7808 elif dir == wx.RIGHT: 7809 insert_pos += 1 7810 7811 if paneInfo.dock_direction == AUI_DOCK_CENTER: 7812 insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1 7813 7814 if drop_pane: 7815 return self.DoDropPane(panes, target, insert_dir, insert_layer, insert_row, insert_pos) 7816 7817 if drop_row: 7818 return self.DoDropRow(panes, target, insert_dir, insert_layer, insert_row) 7819 7820 return True, target 7821 7822 return False, target
7823 7824
7825 - def DoDropNonFloatingPane(self, docks, panes, target, pt):
7826 """ 7827 Handles the situation in which the dropped pane is not floating. 7828 7829 :param `docks`: a list of :class:`AuiDockInfo` classes; 7830 :param `panes`: a list of :class:`AuiPaneInfo` instances; 7831 :param AuiPaneInfo `target`: the target pane containing the toolbar; 7832 :param Point `pt`: a mouse position to check for a drop operation. 7833 """ 7834 7835 screenPt = self._frame.ClientToScreen(pt) 7836 clientSize = self._frame.GetClientSize() 7837 frameRect = GetInternalFrameRect(self._frame, self._docks) 7838 7839 drop = self.CopyTarget(target) 7840 7841 # The result should always be shown 7842 drop.Show() 7843 7844 part = self.HitTest(pt.x, pt.y) 7845 7846 if not part: 7847 return False, target 7848 7849 if part.type == AuiDockUIPart.typeDockSizer: 7850 7851 if len(part.dock.panes) != 1: 7852 return False, target 7853 7854 part = self.GetPanePart(part.dock.panes[0].window) 7855 if not part: 7856 return False, target 7857 7858 if not part.pane: 7859 return False, target 7860 7861 part = self.GetPanePart(part.pane.window) 7862 if not part: 7863 return False, target 7864 7865 insert_dock_row = False 7866 insert_row = part.pane.dock_row 7867 insert_dir = part.pane.dock_direction 7868 insert_layer = part.pane.dock_layer 7869 7870 direction = part.pane.dock_direction 7871 7872 if direction == AUI_DOCK_TOP: 7873 if pt.y >= part.rect.y and pt.y < part.rect.y+auiInsertRowPixels: 7874 insert_dock_row = True 7875 7876 elif direction == AUI_DOCK_BOTTOM: 7877 if pt.y > part.rect.y+part.rect.height-auiInsertRowPixels and \ 7878 pt.y <= part.rect.y + part.rect.height: 7879 insert_dock_row = True 7880 7881 elif direction == AUI_DOCK_LEFT: 7882 if pt.x >= part.rect.x and pt.x < part.rect.x+auiInsertRowPixels: 7883 insert_dock_row = True 7884 7885 elif direction == AUI_DOCK_RIGHT: 7886 if pt.x > part.rect.x+part.rect.width-auiInsertRowPixels and \ 7887 pt.x <= part.rect.x+part.rect.width: 7888 insert_dock_row = True 7889 7890 elif direction == AUI_DOCK_CENTER: 7891 7892 # "new row pixels" will be set to the default, but 7893 # must never exceed 20% of the window size 7894 new_row_pixels_x = auiNewRowPixels 7895 new_row_pixels_y = auiNewRowPixels 7896 7897 if new_row_pixels_x > (part.rect.width*20)/100: 7898 new_row_pixels_x = (part.rect.width*20)/100 7899 7900 if new_row_pixels_y > (part.rect.height*20)/100: 7901 new_row_pixels_y = (part.rect.height*20)/100 7902 7903 # determine if the mouse pointer is in a location that 7904 # will cause a new row to be inserted. The hot spot positions 7905 # are along the borders of the center pane 7906 7907 insert_layer = 0 7908 insert_dock_row = True 7909 pr = part.rect 7910 7911 if pt.x >= pr.x and pt.x < pr.x + new_row_pixels_x: 7912 insert_dir = AUI_DOCK_LEFT 7913 elif pt.y >= pr.y and pt.y < pr.y + new_row_pixels_y: 7914 insert_dir = AUI_DOCK_TOP 7915 elif pt.x >= pr.x + pr.width - new_row_pixels_x and pt.x < pr.x + pr.width: 7916 insert_dir = AUI_DOCK_RIGHT 7917 elif pt.y >= pr.y+ pr.height - new_row_pixels_y and pt.y < pr.y + pr.height: 7918 insert_dir = AUI_DOCK_BOTTOM 7919 else: 7920 return False, target 7921 7922 insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1 7923 7924 if insert_dock_row: 7925 7926 panes = DoInsertDockRow(panes, insert_dir, insert_layer, insert_row) 7927 drop.Dock().Direction(insert_dir).Layer(insert_layer). \ 7928 Row(insert_row).Position(0) 7929 7930 return self.ProcessDockResult(target, drop) 7931 7932 # determine the mouse offset and the pane size, both in the 7933 # direction of the dock itself, and perpendicular to the dock 7934 7935 if part.orientation == wx.VERTICAL: 7936 7937 offset = pt.y - part.rect.y 7938 size = part.rect.GetHeight() 7939 7940 else: 7941 7942 offset = pt.x - part.rect.x 7943 size = part.rect.GetWidth() 7944 7945 drop_position = part.pane.dock_pos 7946 7947 # if we are in the top/left part of the pane, 7948 # insert the pane before the pane being hovered over 7949 if offset <= size/2: 7950 7951 drop_position = part.pane.dock_pos 7952 panes = DoInsertPane(panes, 7953 part.pane.dock_direction, 7954 part.pane.dock_layer, 7955 part.pane.dock_row, 7956 part.pane.dock_pos) 7957 7958 # if we are in the bottom/right part of the pane, 7959 # insert the pane before the pane being hovered over 7960 if offset > size/2: 7961 7962 drop_position = part.pane.dock_pos+1 7963 panes = DoInsertPane(panes, 7964 part.pane.dock_direction, 7965 part.pane.dock_layer, 7966 part.pane.dock_row, 7967 part.pane.dock_pos+1) 7968 7969 7970 drop.Dock(). \ 7971 Direction(part.dock.dock_direction). \ 7972 Layer(part.dock.dock_layer).Row(part.dock.dock_row). \ 7973 Position(drop_position) 7974 7975 return self.ProcessDockResult(target, drop)
7976 7977
7978 - def DoDropLayer(self, docks, target, dock_direction):
7979 """ 7980 Handles the situation in which `target` is a single dock guide. 7981 7982 :param `docks`: a list of :class:`AuiDockInfo` classes; 7983 :param AuiPaneInfo `target`: the target pane; 7984 :param integer `dock_direction`: the docking direction. 7985 """ 7986 7987 drop = self.CopyTarget(target) 7988 7989 if dock_direction == AUI_DOCK_LEFT: 7990 drop.Dock().Left() 7991 drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_LEFT), 7992 GetMaxLayer(docks, AUI_DOCK_BOTTOM)), 7993 GetMaxLayer(docks, AUI_DOCK_TOP)) + 1 7994 7995 elif dock_direction == AUI_DOCK_TOP: 7996 drop.Dock().Top() 7997 drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_TOP), 7998 GetMaxLayer(docks, AUI_DOCK_LEFT)), 7999 GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1 8000 8001 elif dock_direction == AUI_DOCK_RIGHT: 8002 drop.Dock().Right() 8003 drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_RIGHT), 8004 GetMaxLayer(docks, AUI_DOCK_TOP)), 8005 GetMaxLayer(docks, AUI_DOCK_BOTTOM)) + 1 8006 8007 elif dock_direction == AUI_DOCK_BOTTOM: 8008 drop.Dock().Bottom() 8009 drop_new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_BOTTOM), 8010 GetMaxLayer(docks, AUI_DOCK_LEFT)), 8011 GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1 8012 8013 else: 8014 return False, target 8015 8016 8017 drop.Dock().Layer(drop_new_layer) 8018 return self.ProcessDockResult(target, drop)
8019 8020
8021 - def DoDropPane(self, panes, target, dock_direction, dock_layer, dock_row, dock_pos):
8022 """ 8023 Drop a pane in the interface. 8024 8025 :param `panes`: a list of :class:`AuiPaneInfo` classes; 8026 :param AuiPaneInfo `target`: the target pane; 8027 :param integer `dock_direction`: the docking direction; 8028 :param integer `dock_layer`: the docking layer; 8029 :param integer `dock_row`: the docking row; 8030 :param integer `dock_pos`: the docking position. 8031 """ 8032 8033 drop = self.CopyTarget(target) 8034 panes = DoInsertPane(panes, dock_direction, dock_layer, dock_row, dock_pos) 8035 8036 drop.Dock().Direction(dock_direction).Layer(dock_layer).Row(dock_row).Position(dock_pos) 8037 return self.ProcessDockResult(target, drop)
8038 8039
8040 - def DoDropRow(self, panes, target, dock_direction, dock_layer, dock_row):
8041 """ 8042 Insert a row in the interface before dropping. 8043 8044 :param `panes`: a list of :class:`AuiPaneInfo` classes; 8045 :param AuiPaneInfo `target`: the target pane; 8046 :param integer `dock_direction`: the docking direction; 8047 :param integer `dock_layer`: the docking layer; 8048 :param integer `dock_row`: the docking row. 8049 """ 8050 8051 drop = self.CopyTarget(target) 8052 panes = DoInsertDockRow(panes, dock_direction, dock_layer, dock_row) 8053 8054 drop.Dock().Direction(dock_direction).Layer(dock_layer).Row(dock_row).Position(0) 8055 return self.ProcessDockResult(target, drop)
8056 8057
8058 - def ShowHint(self, rect):
8059 """ 8060 Shows the AUI hint window. 8061 8062 :param Rect `rect`: the hint rect calculated in advance. 8063 """ 8064 8065 if rect == self._last_hint: 8066 return 8067 8068 if self._agwFlags & AUI_MGR_RECTANGLE_HINT and wx.Platform != "__WXMAC__": 8069 8070 if self._last_hint != rect: 8071 # remove the last hint rectangle 8072 self._last_hint = wx.Rect(*rect) 8073 self._frame.Refresh() 8074 self._frame.Update() 8075 8076 screendc = wx.ScreenDC() 8077 clip = wx.Region(1, 1, 10000, 10000) 8078 8079 # clip all floating windows, so we don't draw over them 8080 for pane in self._panes: 8081 if pane.IsFloating() and pane.frame.IsShown(): 8082 8083 rect2 = wx.Rect(*pane.frame.GetRect()) 8084 if wx.Platform == "__WXGTK__": 8085 # wxGTK returns the client size, not the whole frame size 8086 rect2.width += 15 8087 rect2.height += 35 8088 rect2.Inflate(5, 5) 8089 8090 clip.SubtractRect(rect2) 8091 8092 # As we can only hide the hint by redrawing the managed window, we 8093 # need to clip the region to the managed window too or we get 8094 # nasty redrawn problems. 8095 clip.IntersectRect(self._frame.GetRect()) 8096 screendc.SetClippingRegionAsRegion(clip) 8097 8098 stipple = PaneCreateStippleBitmap() 8099 brush = wx.BrushFromBitmap(stipple) 8100 screendc.SetBrush(brush) 8101 screendc.SetPen(wx.TRANSPARENT_PEN) 8102 screendc.DrawRectangle(rect.x, rect.y, 5, rect.height) 8103 screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5) 8104 screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height) 8105 screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5) 8106 RefreshDockingGuides(self._guides) 8107 8108 return 8109 8110 if not self._hint_window: 8111 self.CreateHintWindow() 8112 8113 if self._hint_window: 8114 self._hint_window.SetRect(rect) 8115 self._hint_window.Show() 8116 8117 self._hint_fadeamt = self._hint_fademax 8118 8119 if self._agwFlags & AUI_MGR_HINT_FADE: 8120 self._hint_fadeamt = 0 8121 self._hint_window.SetTransparent(self._hint_fadeamt) 8122 8123 if self._action == actionDragFloatingPane and self._action_window: 8124 self._action_window.SetFocus() 8125 8126 if self._hint_fadeamt != self._hint_fademax: # Only fade if we need to 8127 # start fade in timer 8128 self._hint_fadetimer.Start(5) 8129 8130 self._last_hint = wx.Rect(*rect)
8131 8132
8133 - def HideHint(self):
8134 """ Hides a transparent window hint if there is one. """ 8135 8136 # hides a transparent window hint if there is one 8137 if self._hint_window: 8138 self._hint_window.Hide() 8139 8140 self._hint_fadetimer.Stop() 8141 self._last_hint = wx.Rect()
8142 8143
8144 - def IsPaneButtonVisible(self, part):
8145 """ 8146 Returns whether a pane button in the pane caption is visible. 8147 8148 :param AuiDockUIPart `part`: the UI part to analyze. 8149 """ 8150 8151 captionRect = wx.Rect() 8152 8153 for temp_part in self._uiparts: 8154 if temp_part.pane == part.pane and \ 8155 temp_part.type == AuiDockUIPart.typeCaption: 8156 captionRect = temp_part.rect 8157 break 8158 8159 return captionRect.ContainsRect(part.rect)
8160 8161
8162 - def DrawPaneButton(self, dc, part, pt):
8163 """ 8164 Draws a pane button in the caption (convenience function). 8165 8166 :param `dc`: a :class:`DC` device context object; 8167 :param AuiDockUIPart `part`: the UI part to analyze; 8168 :param Point `pt`: the mouse location. 8169 """ 8170 8171 if not self.IsPaneButtonVisible(part): 8172 return 8173 8174 state = AUI_BUTTON_STATE_NORMAL 8175 8176 if part.rect.Contains(pt): 8177 8178 if _VERSION_STRING < "2.9": 8179 leftDown = wx.GetMouseState().LeftDown() 8180 else: 8181 leftDown = wx.GetMouseState().LeftIsDown() 8182 8183 if leftDown: 8184 state = AUI_BUTTON_STATE_PRESSED 8185 else: 8186 state = AUI_BUTTON_STATE_HOVER 8187 8188 self._art.DrawPaneButton(dc, self._frame, part.button.button_id, 8189 state, part.rect, part.pane)
8190 8191
8192 - def RefreshButton(self, part):
8193 """ 8194 Refreshes a pane button in the caption. 8195 8196 :param AuiDockUIPart `part`: the UI part to analyze. 8197 """ 8198 8199 rect = wx.Rect(*part.rect) 8200 rect.Inflate(2, 2) 8201 self._frame.Refresh(True, rect) 8202 self._frame.Update()
8203 8204
8205 - def RefreshCaptions(self):
8206 """ Refreshes all pane captions. """ 8207 8208 for part in self._uiparts: 8209 if part.type == AuiDockUIPart.typeCaption: 8210 self._frame.Refresh(True, part.rect) 8211 self._frame.Update()
8212 8213
8214 - def CalculateHintRect(self, pane_window, pt, offset):
8215 """ 8216 Calculates the drop hint rectangle. 8217 8218 The method first calls :meth:`DoDrop` to determine the exact position the pane would 8219 be at were if dropped. If the pane would indeed become docked at the 8220 specified drop point, the the rectangle hint will be returned in 8221 screen coordinates. Otherwise, an empty rectangle is returned. 8222 8223 :param Window `pane_window`: it is the window pointer of the pane being dragged; 8224 :param Point `pt`: is the mouse position, in client coordinates; 8225 :param Point `offset`: describes the offset that the mouse is from the upper-left 8226 corner of the item being dragged. 8227 """ 8228 8229 # we need to paint a hint rectangle to find out the exact hint rectangle, 8230 # we will create a new temporary layout and then measure the resulting 8231 # rectangle we will create a copy of the docking structures (self._docks) 8232 # so that we don't modify the real thing on screen 8233 8234 rect = wx.Rect() 8235 pane = self.GetPane(pane_window) 8236 8237 attrs = self.GetAttributes(pane) 8238 hint = AuiPaneInfo() 8239 hint = self.SetAttributes(hint, attrs) 8240 8241 if hint.name != "__HINT__": 8242 self._oldname = hint.name 8243 8244 hint.name = "__HINT__" 8245 hint.PaneBorder(True) 8246 hint.Show() 8247 8248 if not hint.IsOk(): 8249 hint.name = self._oldname 8250 return rect 8251 8252 docks, panes = CopyDocksAndPanes2(self._docks, self._panes) 8253 8254 # remove any pane already there which bears the same window 8255 # this happens when you are moving a pane around in a dock 8256 for ii in xrange(len(panes)): 8257 if panes[ii].window == pane_window: 8258 docks = RemovePaneFromDocks(docks, panes[ii]) 8259 panes.pop(ii) 8260 break 8261 8262 # find out where the new pane would be 8263 allow, hint = self.DoDrop(docks, panes, hint, pt, offset) 8264 8265 if not allow: 8266 return rect 8267 8268 panes.append(hint) 8269 8270 sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False) 8271 8272 client_size = self._frame.GetClientSize() 8273 sizer.SetDimension(0, 0, client_size.x, client_size.y) 8274 sizer.Layout() 8275 8276 sought = "__HINT__" 8277 8278 # For a notebook page, actually look for the notebook itself. 8279 if hint.IsNotebookPage(): 8280 id = hint.notebook_id 8281 for pane in panes: 8282 if pane.IsNotebookControl() and pane.notebook_id==id: 8283 sought = pane.name 8284 break 8285 8286 for part in uiparts: 8287 if part.pane and part.pane.name == sought: 8288 rect.Union(wx.RectPS(part.sizer_item.GetPosition(), 8289 part.sizer_item.GetSize())) 8290 8291 sizer.Destroy() 8292 8293 # check for floating frame ... 8294 if rect.IsEmpty(): 8295 for p in panes: 8296 if p.name == sought and p.IsFloating(): 8297 return wx.RectPS(p.floating_pos, p.floating_size) 8298 8299 if rect.IsEmpty(): 8300 return rect 8301 8302 # actually show the hint rectangle on the screen 8303 rect.x, rect.y = self._frame.ClientToScreen((rect.x, rect.y)) 8304 if self._frame.GetLayoutDirection() == wx.Layout_RightToLeft: 8305 # Mirror rectangle in RTL mode 8306 rect.x -= rect.GetWidth() 8307 8308 return rect
8309 8310
8311 - def DrawHintRect(self, pane_window, pt, offset):
8312 """ 8313 Calculates the hint rectangle by calling :meth:`CalculateHintRect`. If there is a 8314 rectangle, it shows it by calling :meth:`ShowHint`, otherwise it hides any hint 8315 rectangle currently shown. 8316 8317 :param Window `pane_window`: it is the window pointer of the pane being dragged; 8318 :param Point `pt`: is the mouse position, in client coordinates; 8319 :param Point `offset`: describes the offset that the mouse is from the upper-left 8320 corner of the item being dragged. 8321 """ 8322 8323 rect = self.CalculateHintRect(pane_window, pt, offset) 8324 8325 if rect.IsEmpty(): 8326 self.HideHint() 8327 self._hint_rect = wx.Rect() 8328 else: 8329 self.ShowHint(rect) 8330 self._hint_rect = wx.Rect(*rect)
8331 8332
8333 - def GetPartSizerRect(self, uiparts):
8334 """ 8335 Returns the rectangle surrounding the specified UI parts. 8336 8337 :param list `uiparts`: list of :class:`AuiDockUIPart` parts. 8338 """ 8339 8340 rect = wx.Rect() 8341 8342 for part in self._uiparts: 8343 if part.pane and part.pane.name == "__HINT__": 8344 rect.Union(wx.RectPS(part.sizer_item.GetPosition(), 8345 part.sizer_item.GetSize())) 8346 8347 return rect
8348 8349
8350 - def GetAttributes(self, pane):
8351 """ 8352 Returns all the attributes of a :class:`AuiPaneInfo`. 8353 8354 :param `pane`: a :class:`AuiPaneInfo` instance. 8355 """ 8356 8357 attrs = [] 8358 attrs.extend([pane.window, pane.frame, pane.state, pane.dock_direction, 8359 pane.dock_layer, pane.dock_pos, pane.dock_row, pane.dock_proportion, 8360 pane.floating_pos, pane.floating_size, pane.best_size, 8361 pane.min_size, pane.max_size, pane.caption, pane.name, 8362 pane.buttons, pane.rect, pane.icon, pane.notebook_id, 8363 pane.transparent, pane.snapped, pane.minimize_mode, pane.minimize_target]) 8364 8365 return attrs
8366 8367
8368 - def SetAttributes(self, pane, attrs):
8369 """ 8370 Sets all the attributes contained in `attrs` to a :class:`AuiPaneInfo`. 8371 8372 :param `pane`: a :class:`AuiPaneInfo` instance; 8373 :param list `attrs`: a list of attributes. 8374 """ 8375 8376 pane.window = attrs[0] 8377 pane.frame = attrs[1] 8378 pane.state = attrs[2] 8379 pane.dock_direction = attrs[3] 8380 pane.dock_layer = attrs[4] 8381 pane.dock_pos = attrs[5] 8382 pane.dock_row = attrs[6] 8383 pane.dock_proportion = attrs[7] 8384 pane.floating_pos = attrs[8] 8385 pane.floating_size = attrs[9] 8386 pane.best_size = attrs[10] 8387 pane.min_size = attrs[11] 8388 pane.max_size = attrs[12] 8389 pane.caption = attrs[13] 8390 pane.name = attrs[14] 8391 pane.buttons = attrs[15] 8392 pane.rect = attrs[16] 8393 pane.icon = attrs[17] 8394 pane.notebook_id = attrs[18] 8395 pane.transparent = attrs[19] 8396 pane.snapped = attrs[20] 8397 pane.minimize_mode = attrs[21] 8398 pane.minimize_target = attrs[22] 8399 8400 return pane
8401 8402
8403 - def OnFloatingPaneResized(self, wnd, size):
8404 """ 8405 Handles the resizing of a floating pane. 8406 8407 :param Window `wnd`: the window managed by the pane; 8408 :param Size `size`: the new pane floating size. 8409 """ 8410 8411 # try to find the pane 8412 pane = self.GetPane(wnd) 8413 if not pane.IsOk(): 8414 raise Exception("Pane window not found") 8415 8416 if pane.frame: 8417 indx = self._panes.index(pane) 8418 pane.floating_pos = pane.frame.GetPosition() 8419 pane.floating_size = size 8420 self._panes[indx] = pane 8421 if pane.IsSnappable(): 8422 self.SnapPane(pane, pane.floating_pos, pane.floating_size, True)
8423 8424
8425 - def OnFloatingPaneClosed(self, wnd, event):
8426 """ 8427 Handles the close event of a floating pane. 8428 8429 :param Window `wnd`: the window managed by the pane; 8430 :param `event`: a :class:`CloseEvent` to be processed. 8431 """ 8432 8433 # try to find the pane 8434 pane = self.GetPane(wnd) 8435 if not pane.IsOk(): 8436 raise Exception("Pane window not found") 8437 8438 # fire pane close event 8439 e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE) 8440 e.SetPane(pane) 8441 e.SetCanVeto(event.CanVeto()) 8442 self.ProcessMgrEvent(e) 8443 8444 if e.GetVeto(): 8445 event.Veto() 8446 return 8447 else: 8448 # close the pane, but check that it 8449 # still exists in our pane array first 8450 # (the event handler above might have removed it) 8451 8452 check = self.GetPane(wnd) 8453 if check.IsOk(): 8454 self.ClosePane(pane)
8455 8456
8457 - def OnFloatingPaneActivated(self, wnd):
8458 """ 8459 Handles the activation event of a floating pane. 8460 8461 :param Window `wnd`: the window managed by the pane. 8462 """ 8463 8464 pane = self.GetPane(wnd) 8465 if not pane.IsOk(): 8466 raise Exception("Pane window not found") 8467 8468 if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE: 8469 ret, self._panes = SetActivePane(self._panes, wnd) 8470 self.RefreshCaptions() 8471 self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, wnd, canVeto=False)
8472 8473
8474 - def OnFloatingPaneMoved(self, wnd, eventOrPt):
8475 """ 8476 Handles the move event of a floating pane. 8477 8478 :param Window `wnd`: the window managed by the pane; 8479 :param `eventOrPt`: a :class:`MoveEvent` to be processed or an instance of :class:`Point`. 8480 """ 8481 8482 pane = self.GetPane(wnd) 8483 if not pane.IsOk(): 8484 raise Exception("Pane window not found") 8485 8486 if not pane.IsSnappable(): 8487 return 8488 8489 if isinstance(eventOrPt, wx.Point): 8490 pane_pos = wx.Point(*eventOrPt) 8491 else: 8492 pane_pos = eventOrPt.GetPosition() 8493 8494 pane_size = pane.floating_size 8495 8496 self.SnapPane(pane, pane_pos, pane_size, False)
8497 8498
8499 - def SnapPane(self, pane, pane_pos, pane_size, toSnap=False):
8500 """ 8501 Snaps a floating pane to one of the main frame sides. 8502 8503 :param `pane`: a :class:`AuiPaneInfo` instance; 8504 :param Point `pane_pos`: the new pane floating position; 8505 :param Size `pane_size`: the new pane floating size; 8506 :param bool `toSnap`: a bool variable to check if :meth:`SnapPane` was called from 8507 a move event. 8508 """ 8509 8510 if self._from_move: 8511 return 8512 8513 managed_window = self.GetManagedWindow() 8514 wnd_pos = managed_window.GetPosition() 8515 wnd_size = managed_window.GetSize() 8516 snapX, snapY = self._snap_limits 8517 8518 if not toSnap: 8519 pane.snapped = 0 8520 if pane.IsLeftSnappable(): 8521 # Check if we can snap to the left 8522 diff = wnd_pos.x - (pane_pos.x + pane_size.x) 8523 if -snapX <= diff <= snapX: 8524 pane.snapped = wx.LEFT 8525 pane.floating_pos = wx.Point(wnd_pos.x-pane_size.x, pane_pos.y) 8526 elif pane.IsTopSnappable(): 8527 # Check if we can snap to the top 8528 diff = wnd_pos.y - (pane_pos.y + pane_size.y) 8529 if -snapY <= diff <= snapY: 8530 pane.snapped = wx.TOP 8531 pane.floating_pos = wx.Point(pane_pos.x, wnd_pos.y-pane_size.y) 8532 elif pane.IsRightSnappable(): 8533 # Check if we can snap to the right 8534 diff = pane_pos.x - (wnd_pos.x + wnd_size.x) 8535 if -snapX <= diff <= snapX: 8536 pane.snapped = wx.RIGHT 8537 pane.floating_pos = wx.Point(wnd_pos.x + wnd_size.x, pane_pos.y) 8538 elif pane.IsBottomSnappable(): 8539 # Check if we can snap to the bottom 8540 diff = pane_pos.y - (wnd_pos.y + wnd_size.y) 8541 if -snapY <= diff <= snapY: 8542 pane.snapped = wx.BOTTOM 8543 pane.floating_pos = wx.Point(pane_pos.x, wnd_pos.y + wnd_size.y) 8544 8545 self.RepositionPane(pane, wnd_pos, wnd_size)
8546 8547
8548 - def RepositionPane(self, pane, wnd_pos, wnd_size):
8549 """ 8550 Repositions a pane after the main frame has been moved/resized. 8551 8552 :param `pane`: a :class:`AuiPaneInfo` instance; 8553 :param Point `wnd_pos`: the main frame position; 8554 :param Size `wnd_size`: the main frame size. 8555 """ 8556 8557 pane_pos = pane.floating_pos 8558 pane_size = pane.floating_size 8559 8560 snap = pane.snapped 8561 if snap == wx.LEFT: 8562 floating_pos = wx.Point(wnd_pos.x - pane_size.x, pane_pos.y) 8563 elif snap == wx.TOP: 8564 floating_pos = wx.Point(pane_pos.x, wnd_pos.y - pane_size.y) 8565 elif snap == wx.RIGHT: 8566 floating_pos = wx.Point(wnd_pos.x + wnd_size.x, pane_pos.y) 8567 elif snap == wx.BOTTOM: 8568 floating_pos = wx.Point(pane_pos.x, wnd_pos.y + wnd_size.y) 8569 8570 if snap: 8571 if pane_pos != floating_pos: 8572 pane.floating_pos = floating_pos 8573 self._from_move = True 8574 pane.frame.SetPosition(pane.floating_pos) 8575 self._from_move = False
8576 8577
8578 - def OnGripperClicked(self, pane_window, start, offset):
8579 """ 8580 Handles the mouse click on the pane gripper. 8581 8582 :param Window `pane_window`: the window managed by the pane; 8583 :param Point `start`: the mouse-click position; 8584 :param Point `offset`: an offset point from the `start` position. 8585 """ 8586 8587 # try to find the pane 8588 paneInfo = self.GetPane(pane_window) 8589 8590 if not paneInfo.IsOk(): 8591 raise Exception("Pane window not found") 8592 8593 if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE: 8594 # set the caption as active 8595 ret, self._panes = SetActivePane(self._panes, pane_window) 8596 self.RefreshCaptions() 8597 self.FireEvent(wxEVT_AUI_PANE_ACTIVATED, pane_window, canVeto=False) 8598 8599 self._action_part = None 8600 self._action_pane = paneInfo 8601 self._action_window = pane_window 8602 self._action_start = start 8603 self._action_offset = offset 8604 self._toolbar_action_offset = wx.Point(*self._action_offset) 8605 8606 self._frame.CaptureMouse() 8607 8608 if paneInfo.IsDocked(): 8609 self._action = actionClickCaption 8610 else: 8611 if paneInfo.IsToolbar(): 8612 self._action = actionDragToolbarPane 8613 else: 8614 self._action = actionDragFloatingPane 8615 8616 if paneInfo.frame: 8617 8618 windowPt = paneInfo.frame.GetRect().GetTopLeft() 8619 originPt = paneInfo.frame.ClientToScreen(wx.Point()) 8620 self._action_offset += originPt - windowPt 8621 self._toolbar_action_offset = wx.Point(*self._action_offset) 8622 8623 if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: 8624 paneInfo.frame.SetTransparent(150) 8625 8626 if paneInfo.IsToolbar(): 8627 self._frame.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
8628 8629
8630 - def OnRender(self, event):
8631 """ 8632 Draws all of the pane captions, sashes, backgrounds, captions, grippers, pane borders and buttons. 8633 It renders the entire user interface. It binds the ``EVT_AUI_RENDER`` event. 8634 8635 :param `event`: an instance of :class:`AuiManagerEvent`. 8636 """ 8637 8638 # if the frame is about to be deleted, don't bother 8639 if not self._frame or self._frame.IsBeingDeleted(): 8640 return 8641 8642 if not self._frame.GetSizer(): 8643 return 8644 8645 mouse = wx.GetMouseState() 8646 mousePos = wx.Point(mouse.GetX(), mouse.GetY()) 8647 point = self._frame.ScreenToClient(mousePos) 8648 art = self._art 8649 8650 dc = event.GetDC() 8651 8652 for part in self._uiparts: 8653 8654 # don't draw hidden pane items or items that aren't windows 8655 if part.sizer_item and ((not part.sizer_item.IsWindow() and \ 8656 not part.sizer_item.IsSpacer() and \ 8657 not part.sizer_item.IsSizer()) or \ 8658 not part.sizer_item.IsShown()): 8659 8660 continue 8661 8662 ptype = part.type 8663 8664 if ptype in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]: 8665 art.DrawSash(dc, self._frame, part.orientation, part.rect) 8666 8667 elif ptype == AuiDockUIPart.typeBackground: 8668 art.DrawBackground(dc, self._frame, part.orientation, part.rect) 8669 8670 elif ptype == AuiDockUIPart.typeCaption: 8671 art.DrawCaption(dc, self._frame, part.pane.caption, part.rect, part.pane) 8672 8673 elif ptype == AuiDockUIPart.typeGripper: 8674 art.DrawGripper(dc, self._frame, part.rect, part.pane) 8675 8676 elif ptype == AuiDockUIPart.typePaneBorder: 8677 art.DrawBorder(dc, self._frame, part.rect, part.pane) 8678 8679 elif ptype == AuiDockUIPart.typePaneButton: 8680 self.DrawPaneButton(dc, part, point)
8681 8682
8683 - def Repaint(self, dc=None):
8684 """ 8685 Repaints the entire frame decorations (sashes, borders, buttons and so on). 8686 It renders the entire user interface. 8687 8688 :param `dc`: if not ``None``, an instance of :class:`PaintDC`. 8689 """ 8690 8691 w, h = self._frame.GetClientSize() 8692 8693 # Figure out which dc to use; if one 8694 # has been specified, use it, otherwise 8695 # make a client dc 8696 if dc is None: 8697 client_dc = wx.ClientDC(self._frame) 8698 dc = client_dc 8699 8700 # If the frame has a toolbar, the client area 8701 # origin will not be (0, 0). 8702 pt = self._frame.GetClientAreaOrigin() 8703 if pt.x != 0 or pt.y != 0: 8704 dc.SetDeviceOrigin(pt.x, pt.y) 8705 8706 # Render all the items 8707 self.Render(dc)
8708 8709
8710 - def Render(self, dc):
8711 """ 8712 Fires a render event, which is normally handled by :meth:`OnRender`. This allows the 8713 render function to be overridden via the render event. 8714 8715 This can be useful for painting custom graphics in the main window. 8716 Default behavior can be invoked in the overridden function by calling 8717 :meth:`OnRender`. 8718 8719 :param `dc`: a :class:`DC` device context object. 8720 """ 8721 8722 e = AuiManagerEvent(wxEVT_AUI_RENDER) 8723 e.SetManager(self) 8724 e.SetDC(dc) 8725 self.ProcessMgrEvent(e)
8726 8727
8728 - def OnCaptionDoubleClicked(self, pane_window):
8729 """ 8730 Handles the mouse double click on the pane caption. 8731 8732 :param Window `pane_window`: the window managed by the pane. 8733 """ 8734 8735 # try to find the pane 8736 paneInfo = self.GetPane(pane_window) 8737 if not paneInfo.IsOk(): 8738 raise Exception("Pane window not found") 8739 8740 if not paneInfo.IsFloatable() or not paneInfo.IsDockable() or \ 8741 self._agwFlags & AUI_MGR_ALLOW_FLOATING == 0: 8742 return 8743 8744 indx = self._panes.index(paneInfo) 8745 win_rect = None 8746 8747 if paneInfo.IsFloating(): 8748 if paneInfo.name.startswith("__floating__"): 8749 # It's a floating tab from a AuiNotebook 8750 notebook = paneInfo.window.__aui_notebook__ 8751 notebook.ReDockPage(paneInfo) 8752 self.Update() 8753 return 8754 else: 8755 8756 e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True) 8757 if e.GetVeto(): 8758 self.HideHint() 8759 ShowDockingGuides(self._guides, False) 8760 return 8761 8762 win_rect = paneInfo.frame.GetRect() 8763 paneInfo.Dock() 8764 if paneInfo.IsToolbar(): 8765 paneInfo = self.SwitchToolBarOrientation(paneInfo) 8766 8767 e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False) 8768 8769 else: 8770 8771 e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, paneInfo, canVeto=True) 8772 if e.GetVeto(): 8773 return 8774 8775 # float the window 8776 if paneInfo.IsMaximized(): 8777 self.RestorePane(paneInfo) 8778 8779 if paneInfo.floating_pos == wx.Point(-1, -1): 8780 captionSize = self._art.GetMetric(AUI_DOCKART_CAPTION_SIZE) 8781 paneInfo.floating_pos = pane_window.GetScreenPosition() 8782 paneInfo.floating_pos.y -= captionSize 8783 8784 paneInfo.Float() 8785 e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, paneInfo, canVeto=False) 8786 8787 self._panes[indx] = paneInfo 8788 self.Update() 8789 8790 if win_rect and self._agwFlags & AUI_MGR_ANIMATE_FRAMES: 8791 paneInfo = self.GetPane(pane_window) 8792 pane_rect = paneInfo.window.GetScreenRect() 8793 self.AnimateDocking(win_rect, pane_rect)
8794 8795
8796 - def OnPaint(self, event):
8797 """ 8798 Handles the ``wx.EVT_PAINT`` event for :class:`AuiManager`. 8799 8800 :param `event`: an instance of :class:`PaintEvent` to be processed. 8801 """ 8802 8803 dc = wx.PaintDC(self._frame) 8804 self.Repaint(dc)
8805 8806
8807 - def OnEraseBackground(self, event):
8808 """ 8809 Handles the ``wx.EVT_ERASE_BACKGROUND`` event for :class:`AuiManager`. 8810 8811 :param `event`: :class:`EraseEvent` to be processed. 8812 8813 :note: This is intentionally empty (excluding wxMAC) to reduce 8814 flickering while drawing. 8815 """ 8816 8817 if wx.Platform == "__WXMAC__": 8818 event.Skip()
8819 8820
8821 - def OnSize(self, event):
8822 """ 8823 Handles the ``wx.EVT_SIZE`` event for :class:`AuiManager`. 8824 8825 :param `event`: a :class:`SizeEvent` to be processed. 8826 """ 8827 8828 skipped = False 8829 if isinstance(self._frame, AuiFloatingFrame) and self._frame.IsShownOnScreen(): 8830 skipped = True 8831 event.Skip() 8832 8833 if self._frame: 8834 8835 self.DoFrameLayout() 8836 if wx.Platform == "__WXMAC__": 8837 self._frame.Refresh() 8838 else: 8839 self.Repaint() 8840 8841 if isinstance(self._frame, wx.MDIParentFrame) or isinstance(self._frame, tabmdi.AuiMDIClientWindow) \ 8842 or isinstance(self._frame, tabmdi.AuiMDIParentFrame): 8843 # for MDI parent frames, this event must not 8844 # be "skipped". In other words, the parent frame 8845 # must not be allowed to resize the client window 8846 # after we are finished processing sizing changes 8847 return 8848 8849 if not skipped: 8850 event.Skip() 8851 8852 # For the snap to screen... 8853 self.OnMove(None)
8854 8855
8856 - def OnFindManager(self, event):
8857 """ 8858 Handles the ``EVT_AUI_FIND_MANAGER`` event for :class:`AuiManager`. 8859 8860 :param `event`: a :class:`AuiManagerEvent` event to be processed. 8861 """ 8862 8863 # Initialize to None 8864 event.SetManager(None) 8865 8866 if not self._frame: 8867 return 8868 8869 # See it this window wants to overwrite 8870 self._frame.ProcessEvent(event) 8871 8872 # if no, it must be us 8873 if not event.GetManager(): 8874 event.SetManager(self)
8875 8876
8877 - def OnSetCursor(self, event):
8878 """ 8879 Handles the ``wx.EVT_SET_CURSOR`` event for :class:`AuiManager`. 8880 8881 :param `event`: a :class:`SetCursorEvent` to be processed. 8882 """ 8883 8884 # determine cursor 8885 part = self.HitTest(event.GetX(), event.GetY()) 8886 cursor = wx.NullCursor 8887 8888 if part: 8889 if part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]: 8890 8891 if not self.CheckMovableSizer(part): 8892 return 8893 8894 if part.orientation == wx.VERTICAL: 8895 cursor = wx.StockCursor(wx.CURSOR_SIZEWE) 8896 else: 8897 cursor = wx.StockCursor(wx.CURSOR_SIZENS) 8898 8899 elif part.type == AuiDockUIPart.typeGripper: 8900 cursor = wx.StockCursor(wx.CURSOR_SIZING) 8901 8902 event.SetCursor(cursor)
8903 8904
8905 - def UpdateButtonOnScreen(self, button_ui_part, event):
8906 """ 8907 Updates/redraws the UI part containing a pane button. 8908 8909 :param AuiDockUIPart `button_ui_part`: the UI part the button belongs to; 8910 :param `event`: a :class:`MouseEvent` to be processed. 8911 """ 8912 8913 hit_test = self.HitTest(*event.GetPosition()) 8914 8915 if not hit_test or not button_ui_part: 8916 return 8917 8918 state = AUI_BUTTON_STATE_NORMAL 8919 8920 if hit_test == button_ui_part: 8921 if event.LeftDown(): 8922 state = AUI_BUTTON_STATE_PRESSED 8923 else: 8924 state = AUI_BUTTON_STATE_HOVER 8925 else: 8926 if event.LeftDown(): 8927 state = AUI_BUTTON_STATE_HOVER 8928 8929 # now repaint the button with hover state 8930 cdc = wx.ClientDC(self._frame) 8931 8932 # if the frame has a toolbar, the client area 8933 # origin will not be (0,0). 8934 pt = self._frame.GetClientAreaOrigin() 8935 if pt.x != 0 or pt.y != 0: 8936 cdc.SetDeviceOrigin(pt.x, pt.y) 8937 8938 if hit_test.pane: 8939 self._art.DrawPaneButton(cdc, self._frame, 8940 button_ui_part.button.button_id, 8941 state, 8942 button_ui_part.rect, hit_test.pane)
8943 8944
8945 - def OnLeftDown(self, event):
8946 """ 8947 Handles the ``wx.EVT_LEFT_DOWN`` event for :class:`AuiManager`. 8948 8949 :param `event`: a :class:`MouseEvent` to be processed. 8950 """ 8951 8952 part = self.HitTest(*event.GetPosition()) 8953 8954 if not part: 8955 event.Skip() 8956 return 8957 8958 self._currentDragItem = -1 8959 8960 if part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]: 8961 8962 if not self.CheckMovableSizer(part): 8963 return 8964 8965 self._action = actionResize 8966 self._action_part = part 8967 self._action_pane = None 8968 self._action_rect = wx.Rect() 8969 self._action_start = wx.Point(event.GetX(), event.GetY()) 8970 self._action_offset = wx.Point(event.GetX() - part.rect.x, 8971 event.GetY() - part.rect.y) 8972 8973 # draw the resize hint 8974 rect = wx.RectPS(self._frame.ClientToScreen(part.rect.GetPosition()), 8975 part.rect.GetSize()) 8976 8977 self._action_rect = wx.Rect(*rect) 8978 8979 if not AuiManager_HasLiveResize(self): 8980 if wx.Platform == "__WXMAC__": 8981 dc = wx.ClientDC(self._frame) 8982 else: 8983 dc = wx.ScreenDC() 8984 8985 DrawResizeHint(dc, rect) 8986 8987 self._frame.CaptureMouse() 8988 8989 elif part.type == AuiDockUIPart.typePaneButton: 8990 if self.IsPaneButtonVisible(part): 8991 self._action = actionClickButton 8992 self._action_part = part 8993 self._action_pane = None 8994 self._action_start = wx.Point(*event.GetPosition()) 8995 self._frame.CaptureMouse() 8996 8997 self.RefreshButton(part) 8998 8999 elif part.type in [AuiDockUIPart.typeCaption, AuiDockUIPart.typeGripper]: 9000 9001 # if we are managing a AuiFloatingFrame window, then 9002 # we are an embedded AuiManager inside the AuiFloatingFrame. 9003 # We want to initiate a toolbar drag in our owner manager 9004 if isinstance(part.pane.window.GetParent(), AuiFloatingFrame): 9005 rootManager = GetManager(part.pane.window) 9006 else: 9007 rootManager = self 9008 9009 offset = wx.Point(event.GetX() - part.rect.x, event.GetY() - part.rect.y) 9010 rootManager.OnGripperClicked(part.pane.window, event.GetPosition(), offset) 9011 9012 if wx.Platform != "__WXMAC__": 9013 event.Skip()
9014 9015
9016 - def OnLeftDClick(self, event):
9017 """ 9018 Handles the ``wx.EVT_LEFT_DCLICK`` event for :class:`AuiManager`. 9019 9020 :param `event`: a :class:`MouseEvent` to be processed. 9021 """ 9022 9023 part = self.HitTest(event.GetX(), event.GetY()) 9024 9025 if part and part.type == AuiDockUIPart.typeCaption: 9026 if isinstance(part.pane.window.GetParent(), AuiFloatingFrame): 9027 rootManager = GetManager(part.pane.window) 9028 else: 9029 rootManager = self 9030 9031 rootManager.OnCaptionDoubleClicked(part.pane.window) 9032 9033 elif part and part.type in [AuiDockUIPart.typeDockSizer, AuiDockUIPart.typePaneSizer]: 9034 # Handles double click on AuiNotebook sashes to unsplit 9035 sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) 9036 for child in part.cont_sizer.GetChildren(): 9037 if child.IsSizer(): 9038 win = child.GetSizer().GetContainingWindow() 9039 if isinstance(win, auibook.AuiNotebook): 9040 win.UnsplitDClick(part, sash_size, event.GetPosition()) 9041 break 9042 9043 event.Skip()
9044 9045
9046 - def DoEndResizeAction(self, event):
9047 """ 9048 Ends a resize action, or for live update, resizes the sash. 9049 9050 :param `event`: a :class:`MouseEvent` to be processed. 9051 """ 9052 9053 clientPt = event.GetPosition() 9054 screenPt = self._frame.ClientToScreen(clientPt) 9055 9056 return self.RestrictResize(clientPt, screenPt, createDC=False)
9057 9058
9059 - def RestrictResize(self, clientPt, screenPt, createDC):
9060 """ Common method between :meth:`DoEndResizeAction` and :meth:`OnLeftUp_Resize`. """ 9061 9062 dock = self._action_part.dock 9063 pane = self._action_part.pane 9064 9065 if createDC: 9066 if wx.Platform == "__WXMAC__": 9067 dc = wx.ClientDC(self._frame) 9068 else: 9069 dc = wx.ScreenDC() 9070 9071 DrawResizeHint(dc, self._action_rect) 9072 self._action_rect = wx.Rect() 9073 9074 newPos = clientPt - self._action_offset 9075 9076 if self._action_part.type == AuiDockUIPart.typeDockSizer: 9077 minPix, maxPix = self.CalculateDockSizerLimits(dock) 9078 else: 9079 if not self._action_part.pane: 9080 return 9081 minPix, maxPix = self.CalculatePaneSizerLimits(dock, pane) 9082 9083 if self._action_part.orientation == wx.HORIZONTAL: 9084 newPos.y = Clip(newPos.y, minPix, maxPix) 9085 else: 9086 newPos.x = Clip(newPos.x, minPix, maxPix) 9087 9088 if self._action_part.type == AuiDockUIPart.typeDockSizer: 9089 9090 partnerDock = self.GetPartnerDock(dock) 9091 sash_size = self._art.GetMetric(AUI_DOCKART_SASH_SIZE) 9092 new_dock_size = 0 9093 direction = dock.dock_direction 9094 9095 if direction == AUI_DOCK_LEFT: 9096 new_dock_size = newPos.x - dock.rect.x 9097 9098 elif direction == AUI_DOCK_TOP: 9099 new_dock_size = newPos.y - dock.rect.y 9100 9101 elif direction == AUI_DOCK_RIGHT: 9102 new_dock_size = dock.rect.x + dock.rect.width - newPos.x - sash_size 9103 9104 elif direction == AUI_DOCK_BOTTOM: 9105 new_dock_size = dock.rect.y + dock.rect.height - newPos.y - sash_size 9106 9107 deltaDockSize = new_dock_size - dock.size 9108 9109 if partnerDock: 9110 if deltaDockSize > partnerDock.size - sash_size: 9111 deltaDockSize = partnerDock.size - sash_size 9112 9113 partnerDock.size -= deltaDockSize 9114 9115 dock.size += deltaDockSize 9116 self.Update() 9117 9118 else: 9119 9120 # determine the new pixel size that the user wants 9121 # this will help us recalculate the pane's proportion 9122 if dock.IsHorizontal(): 9123 oldPixsize = pane.rect.width 9124 newPixsize = oldPixsize + newPos.x - self._action_part.rect.x 9125 9126 else: 9127 oldPixsize = pane.rect.height 9128 newPixsize = oldPixsize + newPos.y - self._action_part.rect.y 9129 9130 totalPixsize, totalProportion = self.GetTotalPixSizeAndProportion(dock) 9131 partnerPane = self.GetPartnerPane(dock, pane) 9132 9133 # prevent division by zero 9134 if totalPixsize <= 0 or totalProportion <= 0 or not partnerPane: 9135 return 9136 9137 # adjust for the surplus 9138 while (oldPixsize > 0 and totalPixsize > 10 and \ 9139 oldPixsize*totalProportion/totalPixsize < pane.dock_proportion): 9140 9141 totalPixsize -= 1 9142 9143 # calculate the new proportion of the pane 9144 9145 newProportion = newPixsize*totalProportion/totalPixsize 9146 newProportion = Clip(newProportion, 1, totalProportion) 9147 deltaProp = newProportion - pane.dock_proportion 9148 9149 if partnerPane.dock_proportion - deltaProp < 1: 9150 deltaProp = partnerPane.dock_proportion - 1 9151 newProportion = pane.dock_proportion + deltaProp 9152 9153 # borrow the space from our neighbor pane to the 9154 # right or bottom (depending on orientation) 9155 partnerPane.dock_proportion -= deltaProp 9156 pane.dock_proportion = newProportion 9157 9158 self.Update() 9159 9160 return True
9161 9162
9163 - def OnLeftUp(self, event):
9164 """ 9165 Handles the ``wx.EVT_LEFT_UP`` event for :class:`AuiManager`. 9166 9167 :param `event`: a :class:`MouseEvent` to be processed. 9168 """ 9169 9170 if self._action == actionResize: 9171 ## self._frame.Freeze() 9172 self.OnLeftUp_Resize(event) 9173 ## self._frame.Thaw() 9174 9175 elif self._action == actionClickButton: 9176 self.OnLeftUp_ClickButton(event) 9177 9178 elif self._action == actionDragFloatingPane: 9179 self.OnLeftUp_DragFloatingPane(event) 9180 9181 elif self._action == actionDragToolbarPane: 9182 self.OnLeftUp_DragToolbarPane(event) 9183 9184 elif self._action == actionDragMovablePane: 9185 self.OnLeftUp_DragMovablePane(event) 9186 9187 else: 9188 event.Skip() 9189 9190 try: 9191 if self._frame.HasCapture(): 9192 self._frame.ReleaseMouse() 9193 except wx.PyDeadObjectError: 9194 pass 9195 9196 self._action = actionNone
9197 9198
9199 - def OnMotion(self, event):
9200 """ 9201 Handles the ``wx.EVT_MOTION`` event for :class:`AuiManager`. 9202 9203 :param `event`: a :class:`MouseEvent` to be processed. 9204 """ 9205 9206 if self._action == actionResize: 9207 self.OnMotion_Resize(event) 9208 9209 elif self._action == actionClickCaption: 9210 self.OnMotion_ClickCaption(event) 9211 9212 elif self._action == actionDragFloatingPane: 9213 self.OnMotion_DragFloatingPane(event) 9214 9215 elif self._action == actionDragToolbarPane: 9216 self.OnMotion_DragToolbarPane(event) 9217 9218 elif self._action == actionDragMovablePane: 9219 self.OnMotion_DragMovablePane(event) 9220 9221 else: 9222 self.OnMotion_Other(event)
9223 9224
9225 - def OnLeaveWindow(self, event):
9226 """ 9227 Handles the ``wx.EVT_LEAVE_WINDOW`` event for :class:`AuiManager`. 9228 9229 :param `event`: a :class:`MouseEvent` to be processed. 9230 """ 9231 9232 if self._hover_button: 9233 self.RefreshButton(self._hover_button) 9234 self._hover_button = None
9235 9236
9237 - def OnCaptureLost(self, event):
9238 """ 9239 Handles the ``wx.EVT_MOUSE_CAPTURE_LOST`` event for :class:`AuiManager`. 9240 9241 :param `event`: a :class:`MouseCaptureLostEvent` to be processed. 9242 """ 9243 9244 # cancel the operation in progress, if any 9245 if self._action != actionNone: 9246 self._action = actionNone 9247 self.HideHint()
9248 9249
9250 - def OnHintFadeTimer(self, event):
9251 """ 9252 Handles the ``wx.EVT_TIMER`` event for :class:`AuiManager`. 9253 9254 :param `event`: a :class:`TimerEvent` to be processed. 9255 """ 9256 9257 if not self._hint_window or self._hint_fadeamt >= self._hint_fademax: 9258 self._hint_fadetimer.Stop() 9259 return 9260 9261 self._hint_fadeamt += 4 9262 self._hint_window.SetTransparent(self._hint_fadeamt)
9263 9264
9265 - def OnMove(self, event):
9266 """ 9267 Handles the ``wx.EVT_MOVE`` event for :class:`AuiManager`. 9268 9269 :param `event`: a :class:`MoveEvent` to be processed. 9270 """ 9271 9272 if event is not None: 9273 event.Skip() 9274 9275 if isinstance(self._frame, AuiFloatingFrame) and self._frame.IsShownOnScreen(): 9276 return 9277 9278 docked, hAlign, vAlign, monitor = self._is_docked 9279 if docked: 9280 self.Snap() 9281 9282 for pane in self._panes: 9283 if pane.IsSnappable(): 9284 if pane.IsFloating() and pane.IsShown(): 9285 self.SnapPane(pane, pane.floating_pos, pane.floating_size, True)
9286 9287
9288 - def OnSysColourChanged(self, event):
9289 """ 9290 Handles the ``wx.EVT_SYS_COLOUR_CHANGED`` event for :class:`AuiManager`. 9291 9292 :param `event`: a :class:`SysColourChangedEvent` to be processed. 9293 """ 9294 9295 # This event is probably triggered by a theme change 9296 # so we have to re-init the art provider. 9297 if self._art: 9298 self._art.Init() 9299 9300 if self._frame: 9301 self.Update() 9302 self._frame.Refresh()
9303 9304
9305 - def OnChildFocus(self, event):
9306 """ 9307 Handles the ``wx.EVT_CHILD_FOCUS`` event for :class:`AuiManager`. 9308 9309 :param `event`: a :class:`ChildFocusEvent` to be processed. 9310 """ 9311 9312 # when a child pane has it's focus set, we should change the 9313 # pane's active state to reflect this. (this is only true if 9314 # active panes are allowed by the owner) 9315 9316 window = event.GetWindow() 9317 if isinstance(window, wx.Dialog): 9318 # Ignore EVT_CHILD_FOCUS events originating from dialogs not 9319 # managed by AUI 9320 rootManager = None 9321 elif isinstance(window.GetParent(), AuiFloatingFrame): 9322 rootManager = GetManager(window) 9323 else: 9324 rootManager = self 9325 9326 if rootManager: 9327 rootManager.ActivatePane(window) 9328 9329 event.Skip()
9330 9331
9332 - def OnMotion_ClickCaption(self, event):
9333 """ 9334 Sub-handler for the :meth:`OnMotion` event. 9335 9336 :param `event`: a :class:`MouseEvent` to be processed. 9337 """ 9338 9339 clientPt = event.GetPosition() 9340 screenPt = self._frame.ClientToScreen(clientPt) 9341 9342 drag_x_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_X) 9343 drag_y_threshold = wx.SystemSettings.GetMetric(wx.SYS_DRAG_Y) 9344 9345 if not self._action_pane: 9346 return 9347 9348 # we need to check if the mouse is now being dragged 9349 if not (abs(clientPt.x - self._action_start.x) > drag_x_threshold or \ 9350 abs(clientPt.y - self._action_start.y) > drag_y_threshold): 9351 9352 return 9353 9354 # dragged -- we need to change the mouse action to 'drag' 9355 if self._action_pane.IsToolbar(): 9356 self._action = actionDragToolbarPane 9357 self._action_window = self._action_pane.window 9358 9359 elif self._action_pane.IsFloatable() and self._agwFlags & AUI_MGR_ALLOW_FLOATING: 9360 9361 e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, self._action_pane, canVeto=True) 9362 if e.GetVeto(): 9363 return 9364 9365 self._action = actionDragFloatingPane 9366 9367 # set initial float position 9368 self._action_pane.floating_pos = screenPt - self._action_offset 9369 9370 # float the window 9371 if self._action_pane.IsMaximized(): 9372 self.RestorePane(self._action_pane) 9373 9374 self._action_pane.Hide() 9375 self._action_pane.Float() 9376 if wx.Platform == "__WXGTK__": 9377 self._action_pane.Show() 9378 9379 e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, self._action_pane, canVeto=False) 9380 9381 if not self._action_pane.frame: 9382 self.Update() 9383 9384 self._action_window = self._action_pane.window 9385 9386 # adjust action offset for window frame 9387 windowPt = self._action_pane.frame.GetRect().GetTopLeft() 9388 originPt = self._action_pane.frame.ClientToScreen(wx.Point()) 9389 self._toolbar_action_offset = originPt - windowPt 9390 9391 if self._agwFlags & AUI_MGR_USE_NATIVE_MINIFRAMES: 9392 originPt = windowPt + wx.Point(3, 3) 9393 9394 self._action_offset += originPt - windowPt 9395 9396 # action offset is used here to make it feel "natural" to the user 9397 # to drag a docked pane and suddenly have it become a floating frame. 9398 # Sometimes, however, the offset where the user clicked on the docked 9399 # caption is bigger than the width of the floating frame itself, so 9400 # in that case we need to set the action offset to a sensible value 9401 frame_size = self._action_pane.frame.GetSize() 9402 if self._action_offset.x > frame_size.x * 2 / 3: 9403 self._action_offset.x = frame_size.x / 2 9404 if self._action_offset.y > frame_size.y * 2 / 3: 9405 self._action_offset.y = frame_size.y / 2 9406 9407 self.OnMotion_DragFloatingPane(event) 9408 if wx.Platform != "__WXGTK__": 9409 self._action_pane.Show() 9410 9411 self.Update() 9412 9413 elif self._action_pane.IsMovable(): 9414 self._action = actionDragMovablePane 9415 self._action_window = self._action_pane.window
9416 9417
9418 - def OnMotion_Resize(self, event):
9419 """ 9420 Sub-handler for the :meth:`OnMotion` event. 9421 9422 :param `event`: a :class:`MouseEvent` to be processed. 9423 """ 9424 9425 if AuiManager_HasLiveResize(self): 9426 if self._currentDragItem != -1: 9427 self._action_part = self._uiparts[self._currentDragItem] 9428 else: 9429 self._currentDragItem = self._uiparts.index(self._action_part) 9430 9431 if self._frame.HasCapture(): 9432 self._frame.ReleaseMouse() 9433 9434 self.DoEndResizeAction(event) 9435 self._frame.CaptureMouse() 9436 return 9437 9438 if not self._action_part or not self._action_part.dock or not self._action_part.orientation: 9439 return 9440 9441 clientPt = event.GetPosition() 9442 screenPt = self._frame.ClientToScreen(clientPt) 9443 9444 dock = self._action_part.dock 9445 pos = self._action_part.rect.GetPosition() 9446 9447 if self._action_part.type == AuiDockUIPart.typeDockSizer: 9448 minPix, maxPix = self.CalculateDockSizerLimits(dock) 9449 else: 9450 if not self._action_part.pane: 9451 return 9452 9453 pane = self._action_part.pane 9454 minPix, maxPix = self.CalculatePaneSizerLimits(dock, pane) 9455 9456 if self._action_part.orientation == wx.HORIZONTAL: 9457 pos.y = Clip(clientPt.y - self._action_offset.y, minPix, maxPix) 9458 else: 9459 pos.x = Clip(clientPt.x - self._action_offset.x, minPix, maxPix) 9460 9461 hintrect = wx.RectPS(self._frame.ClientToScreen(pos), self._action_part.rect.GetSize()) 9462 9463 if hintrect != self._action_rect: 9464 9465 if wx.Platform == "__WXMAC__": 9466 dc = wx.ClientDC(self._frame) 9467 else: 9468 dc = wx.ScreenDC() 9469 9470 DrawResizeHint(dc, self._action_rect) 9471 DrawResizeHint(dc, hintrect) 9472 self._action_rect = wx.Rect(*hintrect)
9473 9474
9475 - def OnLeftUp_Resize(self, event):
9476 """ 9477 Sub-handler for the :meth:`OnLeftUp` event. 9478 9479 :param `event`: a :class:`MouseEvent` to be processed. 9480 """ 9481 9482 if self._currentDragItem != -1 and AuiManager_HasLiveResize(self): 9483 self._action_part = self._uiparts[self._currentDragItem] 9484 9485 if self._frame.HasCapture(): 9486 self._frame.ReleaseMouse() 9487 9488 self.DoEndResizeAction(event) 9489 self._currentDragItem = -1 9490 return 9491 9492 if not self._action_part or not self._action_part.dock: 9493 return 9494 9495 clientPt = event.GetPosition() 9496 screenPt = self._frame.ClientToScreen(clientPt) 9497 9498 return self.RestrictResize(clientPt, screenPt, createDC=True)
9499 9500
9501 - def OnLeftUp_ClickButton(self, event):
9502 """ 9503 Sub-handler for the :meth:`OnLeftUp` event. 9504 9505 :param `event`: a :class:`MouseEvent` to be processed. 9506 """ 9507 9508 self._hover_button = None 9509 9510 if self._action_part: 9511 self.RefreshButton(self._action_part) 9512 9513 # make sure we're still over the item that was originally clicked 9514 if self._action_part == self.HitTest(*event.GetPosition()): 9515 9516 # fire button-click event 9517 e = AuiManagerEvent(wxEVT_AUI_PANE_BUTTON) 9518 e.SetManager(self) 9519 e.SetPane(self._action_part.pane) 9520 e.SetButton(self._action_part.button.button_id) 9521 self.ProcessMgrEvent(e)
9522 9523
9524 - def CheckPaneMove(self, pane):
9525 """ 9526 Checks if a pane has moved by a visible amount. 9527 9528 :param `pane`: an instance of :class:`AuiPaneInfo`. 9529 """ 9530 9531 win_rect = pane.frame.GetRect() 9532 win_rect.x, win_rect.y = pane.floating_pos 9533 9534 if win_rect == self._last_rect: 9535 return False 9536 9537 # skip the first move event 9538 if self._last_rect.IsEmpty(): 9539 self._last_rect = wx.Rect(*win_rect) 9540 return False 9541 9542 # skip if moving too fast to avoid massive redraws and 9543 # jumping hint windows 9544 if abs(win_rect.x - self._last_rect.x) > 10 or \ 9545 abs(win_rect.y - self._last_rect.y) > 10: 9546 self._last_rect = wx.Rect(*win_rect) 9547 return False 9548 9549 return True
9550 9551
9552 - def OnMotion_DragFloatingPane(self, eventOrPt):
9553 """ 9554 Sub-handler for the :meth:`OnMotion` event. 9555 9556 :param `event`: a :class:`MouseEvent` to be processed. 9557 """ 9558 9559 isPoint = False 9560 if isinstance(eventOrPt, wx.Point): 9561 clientPt = self._frame.ScreenToClient(eventOrPt) 9562 screenPt = wx.Point(*eventOrPt) 9563 isPoint = True 9564 else: 9565 clientPt = eventOrPt.GetPosition() 9566 screenPt = self._frame.ClientToScreen(clientPt) 9567 9568 framePos = wx.Point() 9569 9570 # try to find the pane 9571 pane = self.GetPane(self._action_window) 9572 if not pane.IsOk(): 9573 raise Exception("Pane window not found") 9574 9575 # update floating position 9576 if pane.IsFloating(): 9577 diff = pane.floating_pos - (screenPt - self._action_offset) 9578 pane.floating_pos = screenPt - self._action_offset 9579 9580 framePos = pane.floating_pos 9581 9582 # Move the pane window 9583 if pane.frame: 9584 9585 if diff.x != 0 or diff.y != 0: 9586 if wx.Platform == "__WXMSW__" and (self._agwFlags & AUI_MGR_TRANSPARENT_DRAG) == 0: # and not self.CheckPaneMove(pane): 9587 # return 9588 # HACK: Terrible hack on wxMSW (!) 9589 pane.frame.SetTransparent(254) 9590 9591 self._from_move = True 9592 pane.frame.Move(pane.floating_pos) 9593 self._from_move = False 9594 9595 if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: 9596 pane.frame.SetTransparent(150) 9597 9598 # calculate the offset from the upper left-hand corner 9599 # of the frame to the mouse pointer 9600 action_offset = screenPt - framePos 9601 9602 # is the pane dockable? 9603 if not self.CanDockPanel(pane): 9604 self.HideHint() 9605 ShowDockingGuides(self._guides, False) 9606 return 9607 9608 for paneInfo in self._panes: 9609 9610 if not paneInfo.IsDocked() or not paneInfo.IsShown(): 9611 continue 9612 if paneInfo.IsToolbar() or paneInfo.IsNotebookControl(): 9613 continue 9614 if paneInfo.IsMaximized(): 9615 continue 9616 9617 if paneInfo.IsNotebookPage(): 9618 9619 notebookRoot = GetNotebookRoot(self._panes, paneInfo.notebook_id) 9620 9621 if not notebookRoot or not notebookRoot.IsDocked(): 9622 continue 9623 9624 rc = paneInfo.window.GetScreenRect() 9625 if rc.Contains(screenPt): 9626 if rc.height < 20 or rc.width < 20: 9627 return 9628 9629 self.UpdateDockingGuides(paneInfo) 9630 ShowDockingGuides(self._guides, True) 9631 break 9632 9633 self.DrawHintRect(pane.window, clientPt, action_offset)
9634 9635
9636 - def OnMotion_DragMovablePane(self, eventOrPt):
9637 """ 9638 Sub-handler for the :meth:`OnMotion` event. 9639 9640 :param `event`: a :class:`MouseEvent` to be processed. 9641 """ 9642 9643 # Try to find the pane. 9644 pane = self.GetPane(self._action_window) 9645 if not pane.IsOk(): 9646 raise Exception("Pane window not found") 9647 9648 # Draw a hint for where the window will be moved. 9649 if isinstance(eventOrPt, wx.Point): 9650 pt = wx.Point(*eventOrPt) 9651 else: 9652 pt = eventOrPt.GetPosition() 9653 9654 self.DrawHintRect(self._action_window, pt, wx.Point(0, 0)) 9655 9656 # Reduces flicker. 9657 self._frame.Update()
9658 9659
9660 - def OnLeftUp_DragFloatingPane(self, eventOrPt):
9661 """ 9662 Sub-handler for the :meth:`OnLeftUp` event. 9663 9664 :param `event`: a :class:`MouseEvent` to be processed. 9665 """ 9666 9667 if isinstance(eventOrPt, wx.Point): 9668 clientPt = self._frame.ScreenToClient(eventOrPt) 9669 screenPt = wx.Point(*eventOrPt) 9670 else: 9671 clientPt = eventOrPt.GetPosition() 9672 screenPt = self._frame.ClientToScreen(clientPt) 9673 9674 # try to find the pane 9675 paneInfo = self.GetPane(self._action_window) 9676 if not paneInfo.IsOk(): 9677 raise Exception("Pane window not found") 9678 9679 ret = False 9680 9681 if paneInfo.frame: 9682 9683 # calculate the offset from the upper left-hand corner 9684 # of the frame to the mouse pointer 9685 framePos = paneInfo.frame.GetPosition() 9686 action_offset = screenPt - framePos 9687 9688 # is the pane dockable? 9689 if self.CanDockPanel(paneInfo): 9690 # do the drop calculation 9691 indx = self._panes.index(paneInfo) 9692 ret, paneInfo = self.DoDrop(self._docks, self._panes, paneInfo, clientPt, action_offset) 9693 9694 if ret: 9695 e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True) 9696 if e.GetVeto(): 9697 self.HideHint() 9698 ShowDockingGuides(self._guides, False) 9699 return 9700 9701 e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False) 9702 9703 if self._agwFlags & AUI_MGR_SMOOTH_DOCKING: 9704 self.SmoothDock(paneInfo) 9705 9706 self._panes[indx] = paneInfo 9707 9708 # if the pane is still floating, update it's floating 9709 # position (that we store) 9710 if paneInfo.IsFloating(): 9711 paneInfo.floating_pos = paneInfo.frame.GetPosition() 9712 if paneInfo.frame._transparent != paneInfo.transparent or self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: 9713 paneInfo.frame.SetTransparent(paneInfo.transparent) 9714 paneInfo.frame._transparent = paneInfo.transparent 9715 9716 elif self._has_maximized: 9717 self.RestoreMaximizedPane() 9718 9719 # reorder for dropping to a new notebook 9720 # (caution: this code breaks the reference!) 9721 tempPaneInfo = self.CopyTarget(paneInfo) 9722 self._panes.remove(paneInfo) 9723 self._panes.append(tempPaneInfo) 9724 9725 if ret: 9726 self.Update() 9727 9728 if tempPaneInfo.IsFloating(): 9729 self.SnapPane(tempPaneInfo, tempPaneInfo.floating_pos, tempPaneInfo.floating_size, False) 9730 9731 self.HideHint() 9732 ShowDockingGuides(self._guides, False)
9733 9734
9735 - def OnLeftUp_DragMovablePane(self, event):
9736 """ 9737 Sub-handler for the :meth:`OnLeftUp` event. 9738 9739 :param `event`: a :class:`MouseEvent` to be processed. 9740 """ 9741 9742 # Try to find the pane. 9743 paneInfo = self.GetPane(self._action_window) 9744 if not paneInfo.IsOk(): 9745 raise Exception("Pane window not found") 9746 9747 # Hide the hint as it is no longer needed. 9748 self.HideHint() 9749 9750 # is the pane dockable? 9751 if self.CanDockPanel(paneInfo): 9752 # Move the pane to new position. 9753 pt = event.GetPosition() 9754 # do the drop calculation 9755 indx = self._panes.index(paneInfo) 9756 ret, paneInfo = self.DoDrop(self._docks, self._panes, paneInfo, pt, wx.Point(0,0)) 9757 9758 if ret: 9759 e = self.FireEvent(wxEVT_AUI_PANE_DOCKING, paneInfo, canVeto=True) 9760 if e.GetVeto(): 9761 self.HideHint() 9762 ShowDockingGuides(self._guides, False) 9763 return 9764 9765 e = self.FireEvent(wxEVT_AUI_PANE_DOCKED, paneInfo, canVeto=False) 9766 9767 if self._agwFlags & AUI_MGR_SMOOTH_DOCKING: 9768 self.SmoothDock(paneInfo) 9769 9770 self._panes[indx] = paneInfo 9771 9772 if ret: 9773 # Update the layout to realize new position and e.g. form notebooks if needed. 9774 self.Update() 9775 9776 if self.GetAGWFlags() & AUI_MGR_ALLOW_ACTIVE_PANE: 9777 # Ensure active before doing actual display. 9778 ret, self._panes = SetActivePane(self._panes, paneInfo.window) 9779 9780 # Make changes visible to user. 9781 self.Repaint() 9782 9783 # Cancel the action and release the mouse. 9784 self._action = actionNone 9785 self._frame.ReleaseMouse() 9786 self._action_window = None
9787 9788
9789 - def OnMotion_DragToolbarPane(self, eventOrPt):
9790 """ 9791 Sub-handler for the :meth:`OnMotion` event. 9792 9793 :param `event`: a :class:`MouseEvent` to be processed. 9794 """ 9795 9796 isPoint = False 9797 if isinstance(eventOrPt, wx.Point): 9798 clientPt = self._frame.ScreenToClient(eventOrPt) 9799 screenPt = wx.Point(*eventOrPt) 9800 isPoint = True 9801 else: 9802 clientPt = eventOrPt.GetPosition() 9803 screenPt = self._frame.ClientToScreen(clientPt) 9804 9805 pane = self.GetPane(self._action_window) 9806 if not pane.IsOk(): 9807 raise Exception("Pane window not found") 9808 9809 pane.state |= AuiPaneInfo.actionPane 9810 indx = self._panes.index(pane) 9811 9812 ret = False 9813 wasFloating = pane.IsFloating() 9814 # is the pane dockable? 9815 if self.CanDockPanel(pane): 9816 # do the drop calculation 9817 ret, pane = self.DoDrop(self._docks, self._panes, pane, clientPt, self._action_offset) 9818 9819 # update floating position 9820 if pane.IsFloating(): 9821 pane.floating_pos = screenPt - self._toolbar_action_offset 9822 9823 # move the pane window 9824 if pane.frame: 9825 if wx.Platform == "__WXMSW__" and (self._agwFlags & AUI_MGR_TRANSPARENT_DRAG) == 0: # and not self.CheckPaneMove(pane): 9826 # return 9827 # HACK: Terrible hack on wxMSW (!) 9828 pane.frame.SetTransparent(254) 9829 9830 self._from_move = True 9831 pane.frame.Move(pane.floating_pos) 9832 self._from_move = False 9833 9834 if self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: 9835 pane.frame.SetTransparent(150) 9836 9837 self._panes[indx] = pane 9838 if ret and wasFloating != pane.IsFloating() or (ret and not wasFloating): 9839 wx.CallAfter(self.Update) 9840 9841 # when release the button out of the window. 9842 # TODO: a better fix is needed. 9843 9844 if _VERSION_STRING < "2.9": 9845 leftDown = wx.GetMouseState().LeftDown() 9846 else: 9847 leftDown = wx.GetMouseState().LeftIsDown() 9848 9849 if not leftDown: 9850 self._action = actionNone 9851 self.OnLeftUp_DragToolbarPane(eventOrPt)
9852 9853
9854 - def OnMotion_Other(self, event):
9855 """ 9856 Sub-handler for the :meth:`OnMotion` event. 9857 9858 :param `event`: a :class:`MouseEvent` to be processed. 9859 """ 9860 9861 part = self.HitTest(*event.GetPosition()) 9862 9863 if part and part.type == AuiDockUIPart.typePaneButton \ 9864 and self.IsPaneButtonVisible(part): 9865 if part != self._hover_button: 9866 9867 if self._hover_button: 9868 self.RefreshButton(self._hover_button) 9869 9870 self._hover_button = part 9871 self.RefreshButton(part) 9872 9873 else: 9874 9875 if self._hover_button: 9876 self.RefreshButton(self._hover_button) 9877 else: 9878 event.Skip() 9879 9880 self._hover_button = None
9881 9882
9883 - def OnLeftUp_DragToolbarPane(self, eventOrPt):
9884 """ 9885 Sub-handler for the :meth:`OnLeftUp` event. 9886 9887 :param `event`: a :class:`MouseEvent` to be processed. 9888 """ 9889 9890 isPoint = False 9891 if isinstance(eventOrPt, wx.Point): 9892 clientPt = self._frame.ScreenToClient(eventOrPt) 9893 screenPt = wx.Point(*eventOrPt) 9894 isPoint = True 9895 else: 9896 clientPt = eventOrPt.GetPosition() 9897 screenPt = self._frame.ClientToScreen(clientPt) 9898 9899 # try to find the pane 9900 pane = self.GetPane(self._action_window) 9901 if not pane.IsOk(): 9902 raise Exception("Pane window not found") 9903 9904 if pane.IsFloating(): 9905 pane.floating_pos = pane.frame.GetPosition() 9906 if pane.frame._transparent != pane.transparent or self._agwFlags & AUI_MGR_TRANSPARENT_DRAG: 9907 pane.frame.SetTransparent(pane.transparent) 9908 pane.frame._transparent = pane.transparent 9909 9910 # save the new positions 9911 docks = FindDocks(self._docks, pane.dock_direction, pane.dock_layer, pane.dock_row) 9912 if len(docks) == 1: 9913 dock = docks[0] 9914 pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock) 9915 9916 for i in xrange(len(dock.panes)): 9917 dock.panes[i].dock_pos = pane_positions[i] 9918 9919 pane.state &= ~AuiPaneInfo.actionPane 9920 self.Update()
9921 9922
9923 - def OnPaneButton(self, event):
9924 """ 9925 Handles the ``EVT_AUI_PANE_BUTTON`` event for :class:`AuiManager`. 9926 9927 :param `event`: a :class:`AuiManagerEvent` event to be processed. 9928 """ 9929 9930 if not event.pane: 9931 raise Exception("Pane Info passed to AuiManager.OnPaneButton must be non-null") 9932 9933 pane = event.pane 9934 9935 if event.button == AUI_BUTTON_CLOSE: 9936 9937 if isinstance(pane.window.GetParent(), AuiFloatingFrame): 9938 rootManager = GetManager(pane.window) 9939 else: 9940 rootManager = self 9941 9942 if rootManager != self: 9943 self._frame.Close() 9944 return 9945 9946 # fire pane close event 9947 e = AuiManagerEvent(wxEVT_AUI_PANE_CLOSE) 9948 e.SetManager(self) 9949 e.SetPane(event.pane) 9950 self.ProcessMgrEvent(e) 9951 9952 if not e.GetVeto(): 9953 9954 # close the pane, but check that it 9955 # still exists in our pane array first 9956 # (the event handler above might have removed it) 9957 9958 check = self.GetPane(pane.window) 9959 if check.IsOk(): 9960 self.ClosePane(pane) 9961 9962 self.Update() 9963 9964 # mn this performs the minimizing of a pane 9965 elif event.button == AUI_BUTTON_MINIMIZE: 9966 e = AuiManagerEvent(wxEVT_AUI_PANE_MINIMIZE) 9967 e.SetManager(self) 9968 e.SetPane(event.pane) 9969 self.ProcessMgrEvent(e) 9970 9971 if not e.GetVeto(): 9972 self.MinimizePane(pane) 9973 9974 elif event.button == AUI_BUTTON_MAXIMIZE_RESTORE and not pane.IsMaximized(): 9975 9976 # fire pane close event 9977 e = AuiManagerEvent(wxEVT_AUI_PANE_MAXIMIZE) 9978 e.SetManager(self) 9979 e.SetPane(event.pane) 9980 self.ProcessMgrEvent(e) 9981 9982 if not e.GetVeto(): 9983 9984 self.MaximizePane(pane) 9985 self.Update() 9986 9987 elif event.button == AUI_BUTTON_MAXIMIZE_RESTORE and pane.IsMaximized(): 9988 9989 # fire pane close event 9990 e = AuiManagerEvent(wxEVT_AUI_PANE_RESTORE) 9991 e.SetManager(self) 9992 e.SetPane(event.pane) 9993 self.ProcessMgrEvent(e) 9994 9995 if not e.GetVeto(): 9996 9997 self.RestorePane(pane) 9998 self.Update() 9999 10000 elif event.button == AUI_BUTTON_PIN: 10001 10002 if self._agwFlags & AUI_MGR_ALLOW_FLOATING and pane.IsFloatable(): 10003 e = self.FireEvent(wxEVT_AUI_PANE_FLOATING, pane, canVeto=True) 10004 if e.GetVeto(): 10005 return 10006 10007 pane.Float() 10008 e = self.FireEvent(wxEVT_AUI_PANE_FLOATED, pane, canVeto=False) 10009 10010 self.Update()
10011 10012
10013 - def MinimizePane(self, paneInfo, mgrUpdate=True):
10014 """ 10015 Minimizes a pane in a newly and automatically created :class:`~lib.agw.aui.auibar.AuiToolBar`. 10016 10017 Clicking on the minimize button causes a new :class:`~lib.agw.aui.auibar.AuiToolBar` to be created 10018 and added to the frame manager (currently the implementation is such that 10019 panes at West will have a toolbar at the right, panes at South will have 10020 toolbars at the bottom etc...) and the pane is hidden in the manager. 10021 10022 Clicking on the restore button on the newly created toolbar will result in the 10023 toolbar being removed and the original pane being restored. 10024 10025 :param `paneInfo`: a :class:`AuiPaneInfo` instance for the pane to be minimized; 10026 :param bool `mgrUpdate`: ``True`` to call :meth:`Update` to realize the new layout, 10027 ``False`` otherwise. 10028 10029 .. note:: 10030 10031 The `mgrUpdate` parameter is currently only used while loading perspectives using 10032 :meth:`LoadPerspective`, as minimized panes were not correctly taken into account before. 10033 10034 """ 10035 10036 if not paneInfo.IsToolbar(): 10037 10038 if paneInfo.IsMinimized() and mgrUpdate: 10039 # We are already minimized 10040 return 10041 10042 # Basically the idea is this. 10043 # 10044 # 1) create a toolbar, with a restore button 10045 # 10046 # 2) place the new toolbar in the toolbar area representative of the location of the pane 10047 # (NORTH/SOUTH/EAST/WEST, central area always to the right) 10048 # 10049 # 3) Hide the minimizing pane 10050 10051 # personalize the toolbar style 10052 10053 tbStyle = AUI_TB_DEFAULT_STYLE 10054 posMask = paneInfo.minimize_mode & AUI_MINIMIZE_POS_MASK 10055 captMask = paneInfo.minimize_mode & AUI_MINIMIZE_CAPT_MASK 10056 dockDirection = paneInfo.dock_direction 10057 if captMask != 0: 10058 tbStyle |= AUI_TB_TEXT 10059 10060 if posMask == AUI_MINIMIZE_POS_TOOLBAR: 10061 minimize_toolbar = self.GetPane(paneInfo.minimize_target) 10062 if not minimize_toolbar.IsOk(): 10063 posMask = AUI_MINIMIZE_POS_SMART 10064 if paneInfo.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]: 10065 tbStyle |= AUI_TB_HORZ_LAYOUT 10066 10067 elif paneInfo.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER]: 10068 tbStyle |= AUI_TB_VERTICAL 10069 if captMask == AUI_MINIMIZE_CAPT_SMART: 10070 tbStyle |= AUI_TB_CLOCKWISE 10071 else: 10072 minimize_toolbar = minimize_toolbar.window 10073 10074 elif posMask == AUI_MINIMIZE_POS_SMART: 10075 if paneInfo.dock_direction in [AUI_DOCK_TOP, AUI_DOCK_BOTTOM]: 10076 tbStyle |= AUI_TB_HORZ_LAYOUT 10077 10078 elif paneInfo.dock_direction in [AUI_DOCK_LEFT, AUI_DOCK_RIGHT, AUI_DOCK_CENTER]: 10079 tbStyle |= AUI_TB_VERTICAL 10080 if captMask == AUI_MINIMIZE_CAPT_SMART: 10081 tbStyle |= AUI_TB_CLOCKWISE 10082 10083 elif posMask in [AUI_MINIMIZE_POS_TOP, AUI_MINIMIZE_POS_BOTTOM]: 10084 tbStyle |= AUI_TB_HORZ_LAYOUT 10085 if posMask == AUI_MINIMIZE_POS_TOP: 10086 dockDirection = AUI_DOCK_TOP 10087 else: 10088 dockDirection = AUI_DOCK_BOTTOM 10089 10090 else: 10091 tbStyle |= AUI_TB_VERTICAL 10092 if captMask == AUI_MINIMIZE_CAPT_SMART: 10093 tbStyle |= AUI_TB_CLOCKWISE 10094 if posMask == AUI_MINIMIZE_POS_LEFT: 10095 dockDirection = AUI_DOCK_LEFT 10096 elif posMask == AUI_MINIMIZE_POS_RIGHT: 10097 dockDirection = AUI_DOCK_RIGHT 10098 elif posMask == AUI_MINIMIZE_POS_BOTTOM: 10099 dockDirection = AUI_DOCK_BOTTOM 10100 10101 # Create a new toolbar 10102 # give it the same name as the minimized pane with _min appended 10103 10104 win_rect = paneInfo.window.GetScreenRect() 10105 10106 if posMask != AUI_MINIMIZE_POS_TOOLBAR: 10107 minimize_toolbar = auibar.AuiToolBar(self.GetManagedWindow(), agwStyle=tbStyle) 10108 minimize_toolbar.Hide() 10109 minimize_toolbar.SetToolBitmapSize(wx.Size(16, 16)) 10110 10111 if paneInfo.icon and paneInfo.icon.IsOk(): 10112 restore_bitmap = paneInfo.icon 10113 else: 10114 restore_bitmap = self._art._restore_bitmap 10115 10116 if posMask == AUI_MINIMIZE_POS_TOOLBAR: 10117 xsize, ysize = minimize_toolbar.GetToolBitmapSize() 10118 if xsize != restore_bitmap.GetWidth(): 10119 img = restore_bitmap.ConvertToImage() 10120 img.Rescale(xsize, ysize, wx.IMAGE_QUALITY_HIGH) 10121 restore_bitmap = img.ConvertToBitmap() 10122 10123 target = None 10124 if posMask == AUI_MINIMIZE_POS_TOOLBAR: 10125 target = paneInfo.name 10126 10127 minimize_toolbar.AddSimpleTool(ID_RESTORE_FRAME, paneInfo.caption, restore_bitmap, 10128 _(u"Restore %s")%paneInfo.caption, target=target) 10129 minimize_toolbar.SetAuiManager(self) 10130 minimize_toolbar.Realize() 10131 toolpanelname = paneInfo.name + "_min" 10132 10133 if paneInfo.IsMaximized(): 10134 paneInfo.SetFlag(paneInfo.wasMaximized, True) 10135 10136 if posMask != AUI_MINIMIZE_POS_TOOLBAR: 10137 10138 if dockDirection == AUI_DOCK_TOP: 10139 self.AddPane(minimize_toolbar, AuiPaneInfo(). \ 10140 Name(toolpanelname).Caption(paneInfo.caption). \ 10141 ToolbarPane().Top().BottomDockable(False). \ 10142 LeftDockable(False).RightDockable(False).DestroyOnClose()) 10143 10144 elif dockDirection == AUI_DOCK_BOTTOM: 10145 self.AddPane(minimize_toolbar, AuiPaneInfo(). \ 10146 Name(toolpanelname).Caption(paneInfo.caption). \ 10147 ToolbarPane().Bottom().TopDockable(False). \ 10148 LeftDockable(False).RightDockable(False).DestroyOnClose()) 10149 10150 elif dockDirection == AUI_DOCK_LEFT: 10151 self.AddPane(minimize_toolbar, AuiPaneInfo(). \ 10152 Name(toolpanelname).Caption(paneInfo.caption). \ 10153 ToolbarPane().Left().TopDockable(False). \ 10154 BottomDockable(False).RightDockable(False).DestroyOnClose()) 10155 10156 elif dockDirection in [AUI_DOCK_RIGHT, AUI_DOCK_CENTER]: 10157 self.AddPane(minimize_toolbar, AuiPaneInfo(). \ 10158 Name(toolpanelname).Caption(paneInfo.caption). \ 10159 ToolbarPane().Right().TopDockable(False). \ 10160 LeftDockable(False).BottomDockable(False).DestroyOnClose()) 10161 10162 arr = FindDocks(self._docks, paneInfo.dock_direction, paneInfo.dock_layer, paneInfo.dock_row) 10163 10164 if arr: 10165 dock = arr[0] 10166 paneInfo.previousDockSize = dock.size 10167 10168 paneInfo.previousDockPos = paneInfo.dock_pos 10169 10170 # mark ourselves minimized 10171 paneInfo.Minimize() 10172 paneInfo.Show(False) 10173 self._has_minimized = True 10174 # last, hide the window 10175 if paneInfo.window and paneInfo.window.IsShown(): 10176 paneInfo.window.Show(False) 10177 10178 minimize_toolbar.Show() 10179 10180 if mgrUpdate: 10181 self.Update() 10182 if self._agwFlags & AUI_MGR_ANIMATE_FRAMES: 10183 self.AnimateDocking(win_rect, minimize_toolbar.GetScreenRect())
10184 10185
10186 - def OnRestoreMinimizedPane(self, event):
10187 """ 10188 Handles the ``EVT_AUI_PANE_MIN_RESTORE`` event for :class:`AuiManager`. 10189 10190 :param `event`: an instance of :class:`AuiManagerEvent` to be processed. 10191 """ 10192 10193 self.RestoreMinimizedPane(event.pane)
10194 10195
10196 - def OnPaneDocked(self, event):
10197 """ 10198 Handles the ``EVT_AUI_PANE_DOCKED`` event for :class:`AuiManager`. 10199 10200 :param `event`: an instance of :class:`AuiManagerEvent` to be processed. 10201 """ 10202 10203 event.Skip() 10204 self.RemoveAutoNBCaption(event.GetPane())
10205 10206
10207 - def CreateNotebookBase(self, panes, paneInfo):
10208 """ 10209 Creates an auto-notebook base from a pane, and then add that pane as a page. 10210 10211 :param list `panes`: set of panes to append new notebook base pane to 10212 :param AuiPaneInfo `paneInfo`: the pane to be converted to a new notebook. 10213 """ 10214 10215 # Create base notebook pane ... 10216 nbid = len(self._notebooks) 10217 10218 baseInfo = AuiPaneInfo() 10219 baseInfo.SetDockPos(paneInfo).NotebookControl(nbid). \ 10220 CloseButton(False).SetNameFromNotebookId(). \ 10221 NotebookDockable(False).Floatable(paneInfo.IsFloatable()) 10222 baseInfo.best_size = paneInfo.best_size 10223 panes.append(baseInfo) 10224 10225 # add original pane as tab ... 10226 paneInfo.NotebookPage(nbid)
10227 10228
10229 - def RemoveAutoNBCaption(self, pane):
10230 """ 10231 Removes the caption on newly created automatic notebooks. 10232 10233 :param `pane`: an instance of :class:`AuiPaneInfo` (the target notebook). 10234 """ 10235 10236 if self._agwFlags & AUI_MGR_AUTONB_NO_CAPTION == 0: 10237 return False 10238 10239 def RemoveCaption(): 10240 """ Sub-function used to remove the pane caption on automatic notebooks. """ 10241 10242 if pane.HasNotebook(): 10243 notebook = self._notebooks[pane.notebook_id] 10244 self.GetPane(notebook).CaptionVisible(False).PaneBorder(False) 10245 self.Update()
10246 10247 # it seems the notebook isnt created by this stage, so remove 10248 # the caption a moment later 10249 wx.CallAfter(RemoveCaption) 10250 return True
10251 10252
10253 - def RestoreMinimizedPane(self, paneInfo):
10254 """ 10255 Restores a previously minimized pane. 10256 10257 :param `paneInfo`: a :class:`AuiPaneInfo` instance for the pane to be restored. 10258 """ 10259 10260 panename = paneInfo.name 10261 10262 if paneInfo.minimize_mode & AUI_MINIMIZE_POS_TOOLBAR: 10263 pane = self.GetPane(panename) 10264 hasTarget = True 10265 else: 10266 panename = panename[0:-4] 10267 hasTarget = False 10268 10269 pane = self.GetPane(panename) 10270 pane.SetFlag(pane.needsRestore, True) 10271 10272 if not pane.IsOk(): 10273 panename = paneInfo.name 10274 pane = self.GetPane(panename) 10275 paneInfo = self.GetPane(panename + "_min") 10276 if not paneInfo.IsOk(): 10277 # Already minimized 10278 return 10279 10280 if pane.IsOk(): 10281 if not pane.IsMinimized(): 10282 return 10283 10284 10285 if pane.HasFlag(pane.wasMaximized): 10286 self.SavePreviousDockSizes(pane) 10287 10288 self.ShowPane(pane.window, True) 10289 pane.Show(True) 10290 self._has_minimized = False 10291 pane.SetFlag(pane.optionMinimized, False) 10292 10293 if hasTarget: 10294 targetName = pane.minimize_target 10295 toolbarPane = self.GetPane(targetName) 10296 toolbar = toolbarPane.window 10297 item = toolbar.FindToolByLabel(pane.caption) 10298 toolbar.DeleteTool(item.id) 10299 else: 10300 paneInfo.window.Show(False) 10301 self.DetachPane(paneInfo.window) 10302 paneInfo.Show(False) 10303 paneInfo.Hide() 10304 10305 self.Update()
10306 10307
10308 - def AnimateDocking(self, win_rect, pane_rect):
10309 """ 10310 Animates the minimization/docking of a pane a la Eclipse, using a :class:`ScreenDC` 10311 to draw a "moving docking rectangle" on the screen. 10312 10313 :param Rect `win_rect`: the original pane screen rectangle; 10314 :param Rect `pane_rect`: the newly created toolbar/pane screen rectangle. 10315 10316 :note: This functionality is not available on wxMAC as this platform doesn't have 10317 the ability to use :class:`ScreenDC` to draw on-screen and on Windows > Vista. 10318 """ 10319 10320 if wx.Platform == "__WXMAC__": 10321 # No wx.ScreenDC on the Mac... 10322 return 10323 if wx.Platform == "__WXMSW__" and wx.GetOsVersion()[1] > 5: 10324 # No easy way to handle this on Vista... 10325 return 10326 10327 xstart, ystart = win_rect.x, win_rect.y 10328 xend, yend = pane_rect.x, pane_rect.y 10329 10330 step = self.GetAnimationStep() 10331 10332 wstep = int(abs(win_rect.width - pane_rect.width)/step) 10333 hstep = int(abs(win_rect.height - pane_rect.height)/step) 10334 xstep = int(win_rect.x - pane_rect.x)/step 10335 ystep = int(win_rect.y - pane_rect.y)/step 10336 10337 dc = wx.ScreenDC() 10338 dc.SetLogicalFunction(wx.INVERT) 10339 dc.SetBrush(wx.TRANSPARENT_BRUSH) 10340 dc.SetPen(wx.LIGHT_GREY_PEN) 10341 10342 for i in xrange(int(step)): 10343 width, height = win_rect.width - i*wstep, win_rect.height - i*hstep 10344 x, y = xstart - i*xstep, ystart - i*ystep 10345 new_rect = wx.Rect(x, y, width, height) 10346 dc.DrawRoundedRectangleRect(new_rect, 3) 10347 wx.SafeYield() 10348 wx.MilliSleep(10) 10349 dc.DrawRoundedRectangleRect(new_rect, 3)
10350 10351
10352 - def SmoothDock(self, paneInfo):
10353 """ 10354 This method implements a smooth docking effect for floating panes, similar to 10355 what the PyQT library does with its floating windows. 10356 10357 :param `paneInfo`: an instance of :class:`AuiPaneInfo`. 10358 10359 :note: The smooth docking effect can only be used if you set the ``AUI_MGR_SMOOTH_DOCKING`` 10360 style to :class:`AuiManager`. 10361 """ 10362 10363 if paneInfo.IsToolbar(): 10364 return 10365 10366 if not paneInfo.frame or self._hint_rect.IsEmpty(): 10367 return 10368 10369 hint_rect = self._hint_rect 10370 win_rect = paneInfo.frame.GetScreenRect() 10371 10372 xstart, ystart = win_rect.x, win_rect.y 10373 xend, yend = hint_rect.x, hint_rect.y 10374 10375 step = self.GetAnimationStep()/3 10376 10377 wstep = int((win_rect.width - hint_rect.width)/step) 10378 hstep = int((win_rect.height - hint_rect.height)/step) 10379 xstep = int((win_rect.x - hint_rect.x))/step 10380 ystep = int((win_rect.y - hint_rect.y))/step 10381 10382 for i in xrange(int(step)): 10383 width, height = win_rect.width - i*wstep, win_rect.height - i*hstep 10384 x, y = xstart - i*xstep, ystart - i*ystep 10385 new_rect = wx.Rect(x, y, width, height) 10386 paneInfo.frame.SetRect(new_rect) 10387 wx.MilliSleep(10)
10388 10389
10390 - def SetSnapLimits(self, x, y):
10391 """ 10392 Modifies the snap limits used when snapping the `managed_window` to the screen 10393 (using :meth:`SnapToScreen`) or when snapping the floating panes to one side of the 10394 `managed_window` (using :meth:`SnapPane`). 10395 10396 To change the limit after which the `managed_window` or the floating panes are 10397 automatically stickled to the screen border (or to the `managed_window` side), 10398 set these two variables. Default values are 15 pixels. 10399 10400 :param integer `x`: the minimum horizontal distance below which the snap occurs; 10401 :param integer `y`: the minimum vertical distance below which the snap occurs. 10402 """ 10403 10404 self._snap_limits = (x, y) 10405 self.Snap()
10406 10407
10408 - def Snap(self):
10409 """ 10410 Snaps the main frame to specified position on the screen. 10411 10412 :see: :meth:`SnapToScreen` 10413 """ 10414 10415 snap, hAlign, vAlign, monitor = self._is_docked 10416 if not snap: 10417 return 10418 10419 managed_window = self.GetManagedWindow() 10420 snap_pos = self.GetSnapPosition() 10421 wnd_pos = managed_window.GetPosition() 10422 snapX, snapY = self._snap_limits 10423 10424 if abs(snap_pos.x - wnd_pos.x) < snapX and abs(snap_pos.y - wnd_pos.y) < snapY: 10425 managed_window.SetPosition(snap_pos)
10426 10427
10428 - def SnapToScreen(self, snap=True, monitor=0, hAlign=wx.RIGHT, vAlign=wx.TOP):
10429 """ 10430 Snaps the main frame to specified position on the screen. 10431 10432 :param bool `snap`: whether to snap the main frame or not; 10433 :param integer `monitor`: the monitor display in which snapping the window; 10434 :param integer `hAlign`: the horizontal alignment of the snapping position; 10435 :param integer `vAlign`: the vertical alignment of the snapping position. 10436 """ 10437 10438 if not snap: 10439 self._is_docked = (False, wx.RIGHT, wx.TOP, 0) 10440 return 10441 10442 displayCount = wx.Display.GetCount() 10443 if monitor > displayCount: 10444 raise Exception("Invalid monitor selected: you only have %d monitors"%displayCount) 10445 10446 self._is_docked = (True, hAlign, vAlign, monitor) 10447 self.GetManagedWindow().SetPosition(self.GetSnapPosition())
10448 10449
10450 - def GetSnapPosition(self):
10451 """ Returns the main frame snapping position. """ 10452 10453 snap, hAlign, vAlign, monitor = self._is_docked 10454 10455 display = wx.Display(monitor) 10456 area = display.GetClientArea() 10457 size = self.GetManagedWindow().GetSize() 10458 10459 pos = wx.Point() 10460 if hAlign == wx.LEFT: 10461 pos.x = area.x 10462 elif hAlign == wx.CENTER: 10463 pos.x = area.x + (area.width - size.x)/2 10464 else: 10465 pos.x = area.x + area.width - size.x 10466 10467 if vAlign == wx.TOP: 10468 pos.y = area.y 10469 elif vAlign == wx.CENTER: 10470 pos.y = area.y + (area.height - size.y)/2 10471 else: 10472 pos.y = area.y + area.height - size.y 10473 10474 return pos
10475 10476
10477 - def GetAnimationStep(self):
10478 """ Returns the animation step speed (a float) to use in :meth:`AnimateDocking`. """ 10479 10480 return self._animation_step
10481 10482
10483 - def SetAnimationStep(self, step):
10484 """ 10485 Sets the animation step speed (a float) to use in :meth:`AnimateDocking`. 10486 10487 :param float `step`: the animation speed. 10488 """ 10489 10490 self._animation_step = float(step)
10491 10492
10493 - def RequestUserAttention(self, pane_window):
10494 """ 10495 Requests the user attention by intermittently highlighting the pane caption. 10496 10497 :param Window `pane_window`: the window managed by the pane; 10498 """ 10499 10500 # try to find the pane 10501 paneInfo = self.GetPane(pane_window) 10502 if not paneInfo.IsOk(): 10503 raise Exception("Pane window not found") 10504 10505 dc = wx.ClientDC(self._frame) 10506 10507 # if the frame is about to be deleted, don't bother 10508 if not self._frame or self._frame.IsBeingDeleted(): 10509 return 10510 10511 if not self._frame.GetSizer(): 10512 return 10513 10514 for part in self._uiparts: 10515 if part.pane == paneInfo: 10516 self._art.RequestUserAttention(dc, self._frame, part.pane.caption, part.rect, part.pane) 10517 self._frame.RefreshRect(part.rect, True) 10518 break
10519 10520
10521 - def StartPreviewTimer(self, toolbar):
10522 """ 10523 Starts a timer for sliding in and out a minimized pane. 10524 10525 :param `toolbar`: the :class:`~lib.agw.aui.auibar.AuiToolBar` containing the minimized pane tool. 10526 """ 10527 10528 toolbar_pane = self.GetPane(toolbar) 10529 toolbar_name = toolbar_pane.name 10530 10531 pane_name = toolbar_name[0:-4] 10532 10533 self._sliding_pane = self.GetPane(pane_name) 10534 self._sliding_rect = toolbar.GetScreenRect() 10535 self._sliding_direction = toolbar_pane.dock_direction 10536 self._sliding_frame = None 10537 10538 self._preview_timer.Start(1000, wx.TIMER_ONE_SHOT)
10539 10540
10541 - def StopPreviewTimer(self):
10542 """ Stops a timer for sliding in and out a minimized pane. """ 10543 10544 if self._preview_timer.IsRunning(): 10545 self._preview_timer.Stop() 10546 10547 self.SlideOut() 10548 self._sliding_pane = None
10549 10550
10551 - def SlideIn(self, event):
10552 """ 10553 Handles the ``wx.EVT_TIMER`` event for :class:`AuiManager`. 10554 10555 :param `event`: a :class:`TimerEvent` to be processed. 10556 10557 :note: This is used solely for sliding in and out minimized panes. 10558 """ 10559 10560 window = self._sliding_pane.window 10561 self._sliding_frame = wx.MiniFrame(None, -1, title=_("Pane Preview"), 10562 style=wx.FRAME_TOOL_WINDOW | wx.STAY_ON_TOP | 10563 wx.FRAME_NO_TASKBAR | wx.CAPTION) 10564 window.Reparent(self._sliding_frame) 10565 self._sliding_frame.SetSize((0, 0)) 10566 window.Show() 10567 self._sliding_frame.Show() 10568 10569 size = window.GetBestSize() 10570 10571 startX, startY, stopX, stopY = GetSlidingPoints(self._sliding_rect, size, self._sliding_direction) 10572 10573 step = stopX/10 10574 window_size = 0 10575 10576 for i in xrange(0, stopX, step): 10577 window_size = i 10578 self._sliding_frame.SetDimensions(startX, startY, window_size, stopY) 10579 self._sliding_frame.Refresh() 10580 self._sliding_frame.Update() 10581 wx.MilliSleep(10) 10582 10583 self._sliding_frame.SetDimensions(startX, startY, stopX, stopY) 10584 self._sliding_frame.Refresh() 10585 self._sliding_frame.Update()
10586 10587
10588 - def SlideOut(self):
10589 """ 10590 Slides out a preview of a minimized pane. 10591 10592 :note: This is used solely for sliding in and out minimized panes. 10593 """ 10594 10595 if not self._sliding_frame: 10596 return 10597 10598 window = self._sliding_frame.GetChildren()[0] 10599 size = window.GetBestSize() 10600 10601 startX, startY, stopX, stopY = GetSlidingPoints(self._sliding_rect, size, self._sliding_direction) 10602 10603 step = stopX/10 10604 window_size = 0 10605 10606 for i in xrange(stopX, 0, -step): 10607 window_size = i 10608 self._sliding_frame.SetDimensions(startX, startY, window_size, stopY) 10609 self._sliding_frame.Refresh() 10610 self._sliding_frame.Update() 10611 self._frame.RefreshRect(wx.Rect(startX+window_size, startY, step, stopY)) 10612 self._frame.Update() 10613 wx.MilliSleep(10) 10614 10615 self._sliding_frame.SetDimensions(startX, startY, 0, stopY) 10616 10617 window.Hide() 10618 window.Reparent(self._frame) 10619 10620 self._sliding_frame.Hide() 10621 self._sliding_frame.Destroy() 10622 self._sliding_frame = None 10623 self._sliding_pane = None
10624 10625
10626 -class AuiManager_DCP(AuiManager):
10627 """ 10628 A class similar to :class:`AuiManager` but with a Dummy Center Pane (**DCP**). 10629 The code for this class is still flickery due to the call to :func:`CallAfter` 10630 and the double-update call. 10631 """ 10632
10633 - def __init__(self, *args, **keys):
10634 """ See :meth:`AuiManager.__init__` for the class construction. """ 10635 10636 AuiManager.__init__(self, *args, **keys) 10637 self.hasDummyPane = False
10638 10639
10640 - def _createDummyPane(self):
10641 """ Creates a Dummy Center Pane (**DCP**). """ 10642 10643 if self.hasDummyPane: 10644 return 10645 10646 self.hasDummyPane = True 10647 dummy = wx.Panel(self.GetManagedWindow()) 10648 info = AuiPaneInfo().CenterPane().NotebookDockable(True).Name('dummyCenterPane').DestroyOnClose(True) 10649 self.AddPane(dummy, info)
10650 10651
10652 - def _destroyDummyPane(self):
10653 """ Destroys the Dummy Center Pane (**DCP**). """ 10654 10655 if not self.hasDummyPane: 10656 return 10657 10658 self.hasDummyPane = False 10659 self.ClosePane(self.GetPane('dummyCenterPane'))
10660 10661
10662 - def Update(self):
10663 """ 10664 This method is called after any number of changes are made to any of the 10665 managed panes. :meth:`Update` must be invoked after :meth:`AuiManager.AddPane` or 10666 :meth:`AuiManager.InsertPane` are called in order to "realize" or "commit" the changes. 10667 10668 In addition, any number of changes may be made to :class:`AuiManager` structures 10669 (retrieved with :meth:`AuiManager.GetPane`), but to realize the changes, 10670 :meth:`Update` must be called. This construction allows pane flicker to 10671 be avoided by updating the whole layout at one time. 10672 """ 10673 10674 AuiManager.Update(self) 10675 10676 # check if there's already a center pane (except our dummy pane) 10677 dummyCenterPane = self.GetPane('dummyCenterPane') 10678 haveCenterPane = any((pane != dummyCenterPane) and (pane.dock_direction == AUI_DOCK_CENTER) and 10679 not pane.IsFloating() and pane.IsShown() for pane in self.GetAllPanes()) 10680 if haveCenterPane: 10681 if self.hasDummyPane: 10682 # there's our dummy pane and also another center pane, therefor let's remove our dummy 10683 def do(): 10684 self._destroyDummyPane() 10685 self.Update()
10686 wx.CallAfter(do) 10687 else: 10688 # if we get here, there's no center pane, create our dummy 10689 if not self.hasDummyPane: 10690 self._createDummyPane()
10691